diff --git a/core/src/main/java/com/taobao/arthas/core/advisor/AdviceListenerManager.java b/core/src/main/java/com/taobao/arthas/core/advisor/AdviceListenerManager.java index 0143e390f..bb3aca3d7 100644 --- a/core/src/main/java/com/taobao/arthas/core/advisor/AdviceListenerManager.java +++ b/core/src/main/java/com/taobao/arthas/core/advisor/AdviceListenerManager.java @@ -14,39 +14,45 @@ import com.taobao.arthas.core.shell.system.ProcessAware; /** * - * TODO line 的记录 listener方式? 还是有string为key,不过 classname|method|desc|num 这样子? 判断是否已插入了,可以在两行中间查询,有没有 SpyAPI 的invoke? + * TODO line 的记录 listener方式? 还是有string为key,不过 classname|method|desc|num 这样子? + * 判断是否已插入了,可以在两行中间查询,有没有 SpyAPI 的invoke? * - * TODO trace的怎么搞? trace 只记录一次就可以了 classname|method|desc|trace ? 怎么避免 trace 到 SPY的invoke ?直接忽略? + * TODO trace的怎么搞? trace 只记录一次就可以了 classname|method|desc|trace ? 怎么避免 trace 到 + * SPY的invoke ?直接忽略? * * TODO trace命令可以动态的增加 新的函数进去不?只要关联上同一个 Listener应该是可以的。 * - * TODO 在SPY里放很多的 Object数组,然后动态的设置进去? 比如有新的 Listener来的时候。 这样子连查表都不用了。 甚至可以动态生成 存放这些 Listener数组的类? - * 这样子的话,只要有 Binding那里,查询到一个具体分配好的类, 这样子就可以了? 甚至每个ClassLoader里都动态生成这样子的 存放类,那么这样子不可以避免查 ClassLoader了么? + * TODO 在SPY里放很多的 Object数组,然后动态的设置进去? 比如有新的 Listener来的时候。 这样子连查表都不用了。 甚至可以动态生成 + * 存放这些 Listener数组的类? 这样子的话,只要有 Binding那里,查询到一个具体分配好的类, 这样子就可以了? + * 甚至每个ClassLoader里都动态生成这样子的 存放类,那么这样子不可以避免查 ClassLoader了么? * * 动态为每一个增强类,生成一个新的类,新的类里,有各种的 ID 数组,保存每一个类的每一种 trace 点的信息?? * - * 多个 watch命令 对同一个类,现在的逻辑是,每个watch都有一个自己的 TransForm,但不会重复增强,因为做了判断。 watch命令停止时,也没有去掉增强的代码。 - * 只有reset时 才会去掉。 + * 多个 watch命令 对同一个类,现在的逻辑是,每个watch都有一个自己的 TransForm,但不会重复增强,因为做了判断。 + * watch命令停止时,也没有去掉增强的代码。 只有reset时 才会去掉。 * - * 其实用户想查看局部变量,并不是想查看哪一行! 而是想看某个函数里子调用时的 局部变量的值! 所以实际上是想要一个新的命令,比如 watchinmethod , - * 可以 在某个子调用里, + * 其实用户想查看局部变量,并不是想查看哪一行! 而是想看某个函数里子调用时的 局部变量的值! 所以实际上是想要一个新的命令,比如 watchinmethod + * , 可以 在某个子调用里, * - * TODO 现在的trace 可以输出行号,可能不是很精确,但是可以对应上的。 这个在新的方式里怎么支持? 增加一个 linenumber binding? 从mehtodNode,向上查找到最近的行号? + * TODO 现在的trace 可以输出行号,可能不是很精确,但是可以对应上的。 这个在新的方式里怎么支持? 增加一个 linenumber binding? + * 从mehtodNode,向上查找到最近的行号? * - * TODO 防止重复增强,最重要的应该还是动态增加 annotation,这个才是真正可以做到某一行,某一个子 invoke 都能识别出来的! 无论是 transform多少次! - * 字节码怎么动态加 annotation ? annotation里签名用 url ?的key/value方式表达! 这样子可以有效还原信息 + * TODO 防止重复增强,最重要的应该还是动态增加 annotation,这个才是真正可以做到某一行,某一个子 invoke 都能识别出来的! 无论是 + * transform多少次! 字节码怎么动态加 annotation ? annotation里签名用 url ?的key/value方式表达! + * 这样子可以有效还原信息 * - * TODO 是否考虑一个 trace /watch命令之后,得到一个具体的 Listener ID, 允许在另外的窗口里,再次 trace/watch时指定这个ID,就会查找到,并处理。 - * 这样子的话,真正达到了动态灵活的,一层一层增加的trace ! + * TODO 是否考虑一个 trace /watch命令之后,得到一个具体的 Listener ID, 允许在另外的窗口里,再次 + * trace/watch时指定这个ID,就会查找到,并处理。 这样子的话,真正达到了动态灵活的,一层一层增加的trace ! * * * @author hengyunabc 2020-04-24 * */ public class AdviceListenerManager { - + private static Timer timer = ArthasBootstrap.getInstance().getTimer(); - + private static final FakeBootstrapClassLoader FAKEBOOTSTRAPCLASSLOADER = new FakeBootstrapClassLoader(); + static { timer.scheduleAtFixedRate(new TimerTask() { @@ -78,7 +84,7 @@ public class AdviceListenerManager { } } } - + }, 3000, 3000); } @@ -90,7 +96,7 @@ public class AdviceListenerManager { private String key(String className, String methodName, String methodDesc) { return className + methodName + methodDesc; } - + private String keyForTrace(String className, String owner, String methodName, String methodDesc) { return className + owner + methodName + methodDesc; } @@ -106,7 +112,7 @@ public class AdviceListenerManager { listeners = new ArrayList(); map.put(key, listeners); } - if(!listeners.contains(listener)) { + if (!listeners.contains(listener)) { listeners.add(listener); } } @@ -120,8 +126,7 @@ public class AdviceListenerManager { return listeners; } - - + public void registerTraceAdviceListener(String className, String owner, String methodName, String methodDesc, AdviceListener listener) { @@ -133,12 +138,13 @@ public class AdviceListenerManager { listeners = new ArrayList(); map.put(key, listeners); } - if(!listeners.contains(listener)) { + if (!listeners.contains(listener)) { listeners.add(listener); } } - public List queryTraceAdviceListeners(String className, String owner, String methodName, String methodDesc) { + public List queryTraceAdviceListeners(String className, String owner, String methodName, + String methodDesc) { className = className.replace('/', '.'); String key = keyForTrace(className, owner, methodName, methodDesc); @@ -150,6 +156,7 @@ public class AdviceListenerManager { public static void registerAdviceListener(ClassLoader classLoader, String className, String methodName, String methodDesc, AdviceListener listener) { + classLoader = wrap(classLoader); className = className.replace('/', '.'); ClassLoaderAdviceListenerManager manager = adviceListenerMap.get(classLoader); @@ -167,6 +174,7 @@ public class AdviceListenerManager { public static List queryAdviceListeners(ClassLoader classLoader, String className, String methodName, String methodDesc) { + classLoader = wrap(classLoader); className = className.replace('/', '.'); ClassLoaderAdviceListenerManager manager = adviceListenerMap.get(classLoader); @@ -176,9 +184,10 @@ public class AdviceListenerManager { return null; } - - public static void registerTraceAdviceListener(ClassLoader classLoader, String className, String owner, String methodName, - String methodDesc, AdviceListener listener) { + + public static void registerTraceAdviceListener(ClassLoader classLoader, String className, String owner, + String methodName, String methodDesc, AdviceListener listener) { + classLoader = wrap(classLoader); className = className.replace('/', '.'); ClassLoaderAdviceListenerManager manager = adviceListenerMap.get(classLoader); @@ -189,8 +198,10 @@ public class AdviceListenerManager { } manager.registerTraceAdviceListener(className, owner, methodName, methodDesc, listener); } - public static List queryTraceAdviceListeners(ClassLoader classLoader, String className, String owner, - String methodName, String methodDesc) { + + public static List queryTraceAdviceListeners(ClassLoader classLoader, String className, + String owner, String methodName, String methodDesc) { + classLoader = wrap(classLoader); className = className.replace('/', '.'); ClassLoaderAdviceListenerManager manager = adviceListenerMap.get(classLoader); @@ -200,4 +211,15 @@ public class AdviceListenerManager { return null; } + + private static ClassLoader wrap(ClassLoader classLoader) { + if (classLoader != null) { + return classLoader; + } + return FAKEBOOTSTRAPCLASSLOADER; + } + + private static class FakeBootstrapClassLoader extends ClassLoader { + + } }