diff --git a/README.md b/README.md
index 0e1999a..bead308 100644
--- a/README.md
+++ b/README.md
@@ -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
diff --git a/pom.xml b/pom.xml
index 74973f9..d34c09f 100644
--- a/pom.xml
+++ b/pom.xml
@@ -6,7 +6,7 @@
com.ja-netfilter
ja-netfilter
- 2.2.0
+ 2.2.1
ja-netfilter
A javaagent framework
diff --git a/src/main/java/com/janetfilter/core/Dispatcher.java b/src/main/java/com/janetfilter/core/Dispatcher.java
index cd36e29..d89cd01 100644
--- a/src/main/java/com/janetfilter/core/Dispatcher.java
+++ b/src/main/java/com/janetfilter/core/Dispatcher.java
@@ -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);
}
diff --git a/src/main/java/com/janetfilter/core/Environment.java b/src/main/java/com/janetfilter/core/Environment.java
index 5983972..1afaa24 100644
--- a/src/main/java/com/janetfilter/core/Environment.java
+++ b/src/main/java/com/janetfilter/core/Environment.java
@@ -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 +
diff --git a/src/main/java/com/janetfilter/core/Launcher.java b/src/main/java/com/janetfilter/core/Launcher.java
index 9893400..0251f68 100644
--- a/src/main/java/com/janetfilter/core/Launcher.java
+++ b/src/main/java/com/janetfilter/core/Launcher.java
@@ -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;
diff --git a/src/main/java/com/janetfilter/core/commons/DebugInfo.java b/src/main/java/com/janetfilter/core/commons/DebugInfo.java
index 1d1e990..00cbaac 100644
--- a/src/main/java/com/janetfilter/core/commons/DebugInfo.java
+++ b/src/main/java/com/janetfilter/core/commons/DebugInfo.java
@@ -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);
+ }
+ }
+ }
}
diff --git a/src/main/java/com/janetfilter/core/plugin/MyTransformer.java b/src/main/java/com/janetfilter/core/plugin/MyTransformer.java
index 758744b..2d3570e 100644
--- a/src/main/java/com/janetfilter/core/plugin/MyTransformer.java
+++ b/src/main/java/com/janetfilter/core/plugin/MyTransformer.java
@@ -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 {
+
+ }
}
diff --git a/src/main/java/com/janetfilter/core/utils/DateUtils.java b/src/main/java/com/janetfilter/core/utils/DateUtils.java
index c798b98..070a488 100644
--- a/src/main/java/com/janetfilter/core/utils/DateUtils.java
+++ b/src/main/java/com/janetfilter/core/utils/DateUtils.java
@@ -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) {