请教各位大神:
看greys-anatomy/core/src/main/java/com/github/ompc/greys/core/advisor/Enhancer.java 中的代码,是把spyClassFromGreysClassLoader中的Spy.class 拷一份到 spyClassFromTargetClassLoader中去加载,前提是spyClassFromTargetClassLoader中找不到Spy.class的话。问题是Spy.class是打包在greys-agent.jar 而不是 grey-core.jar 中。spyClassFromGreysClassLoader实际从grey-core.jar是找不到这个Spy.class的,最终还是通过父classloader加载。这里是bootstrap classloader。既然Spy.class 是通过bootstrap加载了,那么spyClassFromTargetClassLoader走的是父委托方式,都会找到bootstrap中的Spy.class, 也就不需要在spyClassFromTargetClassLoader中分别加载了。这不是没有达到“派遣间谍混入对方的classLoader中”的目的么?
`
/*
* 派遣间谍混入对方的classLoader中
*/
private void spy(final ClassLoader targetClassLoader)
throws IOException, NoSuchMethodException, IllegalAccessException, InvocationTargetException {
// 如果对方是bootstrap就算了
if (null == targetClassLoader) {
return;
}
// Enhancer类只可能从greysClassLoader中加载
// 所以找他要ClassLoader是靠谱的
final ClassLoader greysClassLoader = Enhancer.class.getClassLoader();
final String spyClassName = GaStringUtils.SPY_CLASSNAME;
// 从GreysClassLoader中加载Spy
final Class<?> spyClassFromGreysClassLoader = loadSpyClassFromGreysClassLoader(greysClassLoader, spyClassName);
if (null == spyClassFromGreysClassLoader) {
return;
}
// 从目标ClassLoader中尝试加载或定义ClassLoader
Class<?> spyClassFromTargetClassLoader = null;
try {
// 去目标类加载器中找下是否已经存在间谍
// 如果间谍已经存在就算了
spyClassFromTargetClassLoader = targetClassLoader.loadClass(spyClassName);
logger.info("Spy already in targetClassLoader : " + targetClassLoader);
}
// 看来间谍不存在啊
catch (ClassNotFoundException cnfe) {
try {// 在目标类加载器中混入间谍
spyClassFromTargetClassLoader = defineClass(
targetClassLoader,
spyClassName,
toByteArray(Enhancer.class.getResourceAsStream("/" + spyClassName.replace('.', '/') + ".class"))
);
} catch (InvocationTargetException ite) {
if (ite.getCause() instanceof java.lang.LinkageError) {
// CloudEngine 由于 loadClass 不到,会导致 java.lang.LinkageError: loader (instance of com/alipay/cloudengine/extensions/equinox/KernelAceClassLoader): attempted duplicate class definition for name: "com/taobao/arthas/core/advisor/Spy"
// 这里尝试忽略
logger.debug("resolve #112 issues", ite);
} else {
throw ite;
}
}
}
// 无论从哪里取到spyClass,都需要重新初始化一次
// 用以兼容重新加载的场景
// 当然,这样做会给渲染的过程带来一定的性能开销,不过能简化编码复杂度
finally {
if (null != spyClassFromTargetClassLoader) {
// 初始化间谍
invokeStaticMethod(
spyClassFromTargetClassLoader,
"init",
greysClassLoader,
getField(spyClassFromGreysClassLoader, "ON_BEFORE_METHOD").get(null),
getField(spyClassFromGreysClassLoader, "ON_RETURN_METHOD").get(null),
getField(spyClassFromGreysClassLoader, "ON_THROWS_METHOD").get(null),
getField(spyClassFromGreysClassLoader, "BEFORE_INVOKING_METHOD").get(null),
getField(spyClassFromGreysClassLoader, "AFTER_INVOKING_METHOD").get(null),
getField(spyClassFromGreysClassLoader, "THROW_INVOKING_METHOD").get(null)
);
}
}
}
`
请教各位大神:
看greys-anatomy/core/src/main/java/com/github/ompc/greys/core/advisor/Enhancer.java 中的代码,是把spyClassFromGreysClassLoader中的Spy.class 拷一份到 spyClassFromTargetClassLoader中去加载,前提是spyClassFromTargetClassLoader中找不到Spy.class的话。问题是Spy.class是打包在greys-agent.jar 而不是 grey-core.jar 中。spyClassFromGreysClassLoader实际从grey-core.jar是找不到这个Spy.class的,最终还是通过父classloader加载。这里是bootstrap classloader。既然Spy.class 是通过bootstrap加载了,那么spyClassFromTargetClassLoader走的是父委托方式,都会找到bootstrap中的Spy.class, 也就不需要在spyClassFromTargetClassLoader中分别加载了。这不是没有达到“派遣间谍混入对方的classLoader中”的目的么?
`
/*
* 派遣间谍混入对方的classLoader中
*/
private void spy(final ClassLoader targetClassLoader)
throws IOException, NoSuchMethodException, IllegalAccessException, InvocationTargetException {
`