【问题标题】:ASM Bytecode replacement function not completingASM 字节码替换功能未完成
【发布时间】:2016-10-31 16:10:41
【问题描述】:

我有一个稍微复杂的架构,我尝试使用 JVMTI 函数 RetransformClasses 和事件挂钩 ClassLoadFileHook 来检测一个类,同时使用 JNI 进入 Java 空间以执行转换。在ClassLoadFileHook 中,我检查它是否正在为我要检测的类触发,如果是,我对Java 类进行JNI 调用,在该类中我使用ASM 5.0.4 执行检测。也就是说,在 Java 空间中,我得到一个表示检测类的字节数组,然后回调到我的本机代码以应用更新。

我遇到的问题是,在我重新转换类的 Java 代码中,代码在实例化 ClassReader 期间/之后挂起:

/**
 * 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");
    }
}

正如我在代码的 cmets 中提到的,ClassReader intantiation 语句之后没有任何内容被执行。甚至finally 块也没有被执行。我不确定这里会发生什么——为什么实例化一个采用通用字节数组的ClassReader 会导致代码像这样挂起?我实际上并没有对类执行任何操作。

【问题讨论】:

  • 对于任何想知道为什么我不确定new ClassReader 是否没有返回/为什么我不使用调试器的人的旁注——我正在进行的 JNI 调用来自我正在编写的代理,据我所知,我没有使用调试器的奢侈,因为 java 进程只能运行一个代理。如果我弄错了,我当然会感谢有人解释原因,并告诉我如何使用调试器。
  • 我假设您正在触发一个类加载,它隐式锁定正在加载 ASM 类的类加载器。因此,您的代码永远不会进步。否则,你会得到你的输出。
  • “一个java进程只能运行一个代理”?我从来没有听说过这样的限制。可以肯定的是,我只是对其进行了测试,并且运行多个代理没有问题……
  • 此外,您确定实现一个必须调用 Java 空间以执行其实际工作的本机代理是正确的方法吗?为什么不首先实现 Java 代理?
  • @RafaelWinterhalter 你是对的。谢谢!如果您想对此问题添加答案,我很乐意将其标记为正确。

标签: java java-native-interface bytecode java-bytecode-asm javaagents


【解决方案1】:

如果您对 Java 代码的调用导致类加载,则您在加载类的类加载器上隐式同步。我假设您在本机层上触发了这样的类加载,然后当您尝试在 Java 层上再次触发它时被阻止。这就是为什么当您尝试在 Java 中转换类时,您永远不会超越第一个 ASM 类。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2012-12-18
    • 1970-01-01
    • 2021-03-18
    • 2012-01-09
    • 1970-01-01
    • 1970-01-01
    • 2020-10-09
    • 1970-01-01
    相关资源
    最近更新 更多