update the lifecycle of the transformer

Signed-off-by: pengzhile <pengzhile@gmail.com>
This commit is contained in:
pengzhile 2022-01-21 18:10:26 +08:00
parent 389380dda1
commit 3f1d63e02e
8 changed files with 128 additions and 32 deletions

View File

@ -1,4 +1,4 @@
# ja-netfilter v2.2.0
# ja-netfilter v2.2.1
### A javaagent framework
@ -49,7 +49,7 @@ EQUAL,somedomain
* the `ja-netfilter` will **NOT** output debugging information by default
* add environment variable `JANF_DEBUG=1` (log level) and start to enable it
* or add system property `-Djanf.debug=1` (log level) to enable it
* log level: `NONE=0`, `DEBUG=1`, `INFO=2`, `WARN=3`, `ERROR=4`;
* log level: `NONE=0`, `DEBUG=1`, `INFO=2`, `WARN=3`, `ERROR=4`
## Plugin system

View File

@ -6,7 +6,7 @@
<groupId>com.ja-netfilter</groupId>
<artifactId>ja-netfilter</artifactId>
<version>2.2.0</version>
<version>2.2.1</version>
<name>ja-netfilter</name>
<description>A javaagent framework</description>

View File

@ -63,12 +63,24 @@ public final class Dispatcher implements ClassFileTransformer {
try {
for (MyTransformer transformer : globalTransformers) {
classFileBuffer = transformer.transform(className, classFileBuffer, order++);
transformer.before(className, classFileBuffer);
}
for (MyTransformer transformer : globalTransformers) {
classFileBuffer = transformer.preTransform(className, classFileBuffer, order++);
}
for (MyTransformer transformer : transformers) {
classFileBuffer = transformer.transform(className, classFileBuffer, order++);
}
for (MyTransformer transformer : globalTransformers) {
classFileBuffer = transformer.postTransform(className, classFileBuffer, order++);
}
for (MyTransformer transformer : globalTransformers) {
transformer.after(className, classFileBuffer);
}
} catch (Throwable e) {
DebugInfo.error("Transform class failed: " + className, e);
}

View File

@ -7,6 +7,8 @@ import java.io.File;
public final class Environment {
private final String pid;
private final String version;
private final String appName;
private final File baseDir;
private final File agentFile;
private final File configDir;
@ -23,24 +25,34 @@ public final class Environment {
baseDir = agentFile.getParentFile();
if (StringUtils.isEmpty(app)) {
appName = "";
configDir = new File(baseDir, "config");
pluginsDir = new File(baseDir, "plugins");
logsDir = new File(baseDir, "logs");
} else {
app = app.toLowerCase();
configDir = new File(baseDir, "config-" + app);
pluginsDir = new File(baseDir, "plugins-" + app);
logsDir = new File(baseDir, "logs-" + app);
appName = app.toLowerCase();
configDir = new File(baseDir, "config-" + appName);
pluginsDir = new File(baseDir, "plugins-" + appName);
logsDir = new File(baseDir, "logs-" + appName);
}
nativePrefix = StringUtils.randomMethodName(15) + "_";
pid = ProcessUtils.currentId();
version = Launcher.VERSION;
nativePrefix = StringUtils.randomMethodName(15) + "_";
}
public String getPid() {
return pid;
}
public String getVersion() {
return version;
}
public String getAppName() {
return appName;
}
public File getBaseDir() {
return baseDir;
}
@ -69,6 +81,8 @@ public final class Environment {
public String toString() {
return "Environment: {" +
"\n\tpid = " + pid +
", \n\tversion = " + version +
", \n\tappName = " + appName +
", \n\tbaseDir = " + baseDir +
", \n\tagentFile = " + agentFile +
", \n\tconfigDir = " + configDir +

View File

@ -12,7 +12,7 @@ import java.util.jar.JarFile;
public class Launcher {
public static final String ATTACH_ARG = "--attach";
public static final String VERSION = "v2.2.0";
public static final String VERSION = "v2.2.1";
private static boolean loaded = false;

View File

@ -7,10 +7,13 @@ import java.io.File;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.PrintStream;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
public class DebugInfo {
private static final ExecutorService EXECUTOR = Executors.newCachedThreadPool();
private static final String CLASS_NAME = DebugInfo.class.getName();
private static final String LOG_TEMPLATE = "[%s] %s %s : %s%n";
private static final String LOG_TEMPLATE = "%s %-5s [%s] %s-%d : %s%n";
private static final Level LOG_LEVEL;
private static File logFile;
@ -93,26 +96,7 @@ public class DebugInfo {
return;
}
String caller = "UNKNOWN";
StackTraceElement[] traces = new Throwable().getStackTrace();
for (int i = 1, l = traces.length; i < l; i++) { // thank RayGicEFL
StackTraceElement element = traces[i];
if (!CLASS_NAME.equals(element.getClassName())) {
caller = element.toString();
break;
}
}
String outContent = String.format(LOG_TEMPLATE, DateUtils.formatDateTime(), caller, level, content);
if (null == e) {
writeContent(outContent);
return;
}
synchronized (DebugInfo.class) {
writeContent(outContent, System.err);
writeException(e);
}
EXECUTOR.execute(new WriteTask(level, content, e));
}
private static void writeContent(String content) {
@ -173,4 +157,47 @@ public class DebugInfo {
return NONE;
}
}
private static class WriteTask implements Runnable {
private final Level level;
private final String content;
private final Throwable exception;
private final Throwable stackException;
private final String threadName;
WriteTask(Level level, String content, Throwable exception) {
this.level = level;
this.content = content;
this.exception = exception;
this.stackException = new Throwable();
this.threadName = Thread.currentThread().getName();
}
@Override
public void run() {
int line = 0;
String caller = "UNKNOWN";
StackTraceElement[] traces = stackException.getStackTrace();
for (int i = 1, l = traces.length; i < l; i++) { // thank RayGicEFL
StackTraceElement element = traces[i];
if (!CLASS_NAME.equals(element.getClassName())) {
line = element.getLineNumber();
caller = element.getClassName();
break;
}
}
String outContent = String.format(LOG_TEMPLATE, DateUtils.formatDateTimeMicro(), level, threadName, caller, line, content);
if (null == exception) {
writeContent(outContent);
return;
}
synchronized (DebugInfo.class) {
writeContent(outContent, System.err);
writeException(exception);
}
}
}
}

View File

@ -1,9 +1,43 @@
package com.janetfilter.core.plugin;
public interface MyTransformer {
/**
* @return class name like this: package/to/className, null means it's a global transformer
*/
String getHookClassName();
/**
* for global transformers only
*/
default void before(String className, byte[] classBytes) throws Exception {
}
/**
* for global transformers only
*/
default byte[] preTransform(String className, byte[] classBytes, int order) throws Exception {
return transform(className, classBytes, order); // for old version
}
/**
* for normal transformers only
*/
default byte[] transform(String className, byte[] classBytes, int order) throws Exception {
return classBytes;
}
/**
* for global transformers only
*/
default byte[] postTransform(String className, byte[] classBytes, int order) throws Exception {
return classBytes;
}
/**
* for global transformers only
*/
default void after(String className, byte[] classBytes) throws Exception {
}
}

View File

@ -7,6 +7,7 @@ import java.util.Date;
public class DateUtils {
public static final DateFormat FULL_DF = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
public static final DateFormat FULL_MICRO_DF = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss.SSS");
public static final DateFormat DATE_DF = new SimpleDateFormat("yyyy-MM-dd");
public static final DateFormat TIME_DF = new SimpleDateFormat("HH:mm:ss");
@ -15,7 +16,15 @@ public class DateUtils {
}
public static String formatDateTime() {
return FULL_DF.format(new Date());
return formatDateTime(new Date());
}
public static String formatDateTimeMicro(Date date) {
return FULL_MICRO_DF.format(date);
}
public static String formatDateTimeMicro() {
return formatDateTimeMicro(new Date());
}
public static String formatDate(Date date) {