Warning: file_get_contents(/data/phpspider/zhask/data//catemap/4/oop/2.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Java ASM字节码替换功能未完成_Java_Java Native Interface_Bytecode_Java Bytecode Asm_Javaagents - Fatal编程技术网

Java ASM字节码替换功能未完成

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

我有一个稍微复杂的体系结构,在这个体系结构中,我试图使用JVMTI函数和事件挂钩来为一个类提供工具,同时使用JNI进入Java空间来执行转换。在
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你是对的。非常感谢。如果你想为这个问题添加答案,我很乐意将其标记为正确。