Java ASM字节码替换功能未完成
我有一个稍微复杂的体系结构,在这个体系结构中,我试图使用JVMTI函数和事件挂钩来为一个类提供工具,同时使用JNI进入Java空间来执行转换。在Java ASM字节码替换功能未完成,java,java-native-interface,bytecode,java-bytecode-asm,javaagents,Java,Java Native Interface,Bytecode,Java Bytecode Asm,Javaagents,我有一个稍微复杂的体系结构,在这个体系结构中,我试图使用JVMTI函数和事件挂钩来为一个类提供工具,同时使用JNI进入Java空间来执行转换。在ClassLoadFileHook中,我检查是否为我要插入的类触发了它,如果是,我对一个Java类进行JNI调用,在该类中使用执行插入。也就是说,在Java空间中,我得到一个表示插入指令的类的字节数组,然后调用本机代码来应用更新 我遇到的问题是,在我重新转换类的Java代码中,代码在实例化类读取器期间/之后挂起: /** * Transform som
ClassLoadFileHook
中,我检查是否为我要插入的类触发了它,如果是,我对一个Java类进行JNI调用,在该类中使用执行插入。也就是说,在Java空间中,我得到一个表示插入指令的类的字节数组,然后调用本机代码来应用更新
我遇到的问题是,在我重新转换类的Java代码中,代码在实例化类读取器期间/之后挂起:
/**
* Transform some class and then call back down to native code to apply
* the transformation.
*
* @param existingClass The existing class to change.
*/
public synchronized void transformSomeClass(byte[] existingClass) {
System.out.println("Transformation function started. Existing class len: " + existingClass.length);
try {
ClassReader cr = new ClassReader(existingClass);
// No statements below here are being executed.
// I'm also not sure if `new ClassReader` is being successfully
// executed.
System.out.println("After ClassReader instantiation");
ClassWriter cw = new ClassWriter(ClassWriter.COMPUTE_FRAMES);
System.out.println("After ClassWriter instantiation");
ClassVisitor cv =
new MyCustomClassAdapter(cw, this.lineNumberToPlaceUpdate_);
System.out.println("After ClassVisitor instantiation");
cr.accept(cv, 0);
System.out.println("After cv accept.");
System.out.println("Applying class transformation natively.");
// Call back down to native code to apply the update in ClassLoadFileHook.
applyClassTransformNative(cw.toByteArray());
System.out.println("Transformation function ended.");
} catch (Exception e) {
// This is never being fired.
System.err.println("Class transformation could not be completed. Error message: " + e.getMessage());
e.printStackTrace();
} finally {
// This print statement is never executed.
System.err.println("Going back to native code from finally");
}
}
正如我在代码注释中提到的,在ClassReader
intantation语句之后,不会执行任何操作。即使是finally
块也不会执行。我不确定这里会发生什么——为什么实例化一个采用通用字节数组的类读取器会导致代码像这样挂起?我实际上没有对该类执行任何操作。如果对Java代码的调用导致类加载,则在加载类的类加载程序上隐式同步。我假设您在本机层上触发此类类加载,然后在Java层上再次尝试触发时被阻止。这就是为什么在尝试用Java转换类时,您永远不会超越第一个ASM类。对于那些想知道为什么我不确定新的类读取器是否没有返回/为什么我没有使用调试器的人来说,作为旁注,据我所知,我正在进行的JNI调用来自我正在编写的代理,我没有使用调试器的特权,因为java进程只能运行一个代理。如果我弄错了,我当然希望有人解释一下原因,并告诉我如何使用调试器。我假设您正在触发一个类加载,它隐式地锁定正在加载ASM类的类加载程序。因此,您的代码永远不会进步。否则,您将获得输出。“一个java进程只能运行一个代理”?我从未听说过这样的限制。我只是测试了它,可以肯定的是,在运行多个代理时没有问题……此外,您确定实现一个必须调用Java空间才能执行其实际工作的本机代理是正确的方法吗?为什么不首先实现一个Java代理呢?@RafaelWinterhalter你是对的。非常感谢。如果你想为这个问题添加答案,我很乐意将其标记为正确。