support classes load by bootstrap classloader

This commit is contained in:
hengyunabc
2020-05-20 13:01:34 +08:00
parent cead701c71
commit 2f5bc476eb
@@ -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<AdviceListener>();
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<AdviceListener>();
map.put(key, listeners);
}
if(!listeners.contains(listener)) {
if (!listeners.contains(listener)) {
listeners.add(listener);
}
}
public List<AdviceListener> queryTraceAdviceListeners(String className, String owner, String methodName, String methodDesc) {
public List<AdviceListener> 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<AdviceListener> 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<AdviceListener> queryTraceAdviceListeners(ClassLoader classLoader, String className, String owner,
String methodName, String methodDesc) {
public static List<AdviceListener> 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 {
}
}