【问题标题】:Adding try-catch block for injected byte code through ASM通过 ASM 为注入的字节码添加 try-catch 块
【发布时间】:2014-07-22 08:06:21
【问题描述】:

我正在尝试使用 ASM 注入字节码,我想用 try-catch 块包围注入的字节码。但是,我在 onMethodExit 上得到了一个 VerifyError:“不一致的堆栈高度 0 != 1”。

删除 try-catch 块后,它会按预期工作。任何指针都非常感谢。

这是我的代码快照:-----

 protected void onMethodEnter()  {    

        mv.visitInsn(Opcodes.ICONST_0);
        mv.visitVarInsn(ISTORE, okFlag);

        Label startTryBlock = new Label();
        Label endTryBlock = new Label();
        Label startCatchBlock = new Label();

        // Initialization try-catch block
        mv.visitTryCatchBlock(startTryBlock, endTryBlock, startCatchBlock, "java/lang/Exception");

        // starting try block
        mv.visitLabel(startTryBlock);

        mv.visitLdcInsn(className);
        mv.visitLdcInsn(methodName);
        mv.visitLdcInsn(description);
        mv.visitMethodInsn(Opcodes.INVOKESTATIC, "org/sam/agent/trace/RootTracer", "allMethodBegin", "(Ljava/lang/String;Ljava/lang/String;Ljava/lang/String;)Z");
        mv.visitVarInsn(ISTORE, okFlag);

        //ending try  block
        mv.visitLabel(endTryBlock); 
        Label endCatchBlock = new Label();
        mv.visitJumpInsn(GOTO, endCatchBlock);

        // start catch block
        mv.visitLabel(startCatchBlock);
        mv.visitVarInsn(ASTORE, isStatic);

        //ending catch block
        mv.visitLabel(endCatchBlock);
}



private void onMethodExit(int opcode)  {

        Label startTryBlock = new Label();
        Label endTryBlock = new Label();
        Label startCatchBlock = new Label();

        // Initialization try-catch block
        mv.visitTryCatchBlock(startTryBlock, endTryBlock, startCatchBlock, "java/lang/Exception");

        // starting try block
        mv.visitLabel(startTryBlock);

        if(opcode == ATHROW){
            mv.visitInsn(Opcodes.DUP);
            mv.visitLdcInsn(className);
            mv.visitLdcInsn(methodName);
            mv.visitLdcInsn(description);
            mv.visitMethodInsn(Opcodes.INVOKESTATIC, "org/sam/agent/trace/RootTracer", "recordException", "(Ljava/lang/Object;Ljava/lang/String;Ljava/lang/String;Ljava/lang/String;)V");
        }
        mv.visitLdcInsn(className);
        mv.visitLdcInsn(methodName);
        mv.visitLdcInsn(description);
        mv.visitVarInsn(ILOAD, okFlag);
        mv.visitLdcInsn(opcode);
        mv.visitMethodInsn(Opcodes.INVOKESTATIC, "org/sam/agent/trace/RootTracer", "MethodEnd", "(Ljava/lang/String;Ljava/lang/String;Ljava/lang/String;ZI)V");

        // ending try block
        mv.visitLabel(endTryBlock); 
        Label endCatchBlock = new Label();
        mv.visitJumpInsn(GOTO, endCatchBlock);

        // starting catch block
        mv.visitLabel(startCatchBlock);
        mv.visitVarInsn(ASTORE, isStatic); // FAILED Here

        // ending catch block
        mv.visitLabel(endCatchBlock);
    }

【问题讨论】:

    标签: java java-bytecode-asm


    【解决方案1】:

    任何 Java 方法都在操作数堆栈上执行。在其执行期间,值被压入堆栈或从堆栈中弹出。当您在 onMethodExit(int)-emitted 方法中使用跳转指令时,您需要确保操作数堆栈上的任何 目标的元素类型完全相同跳转指令。这些元素类型必须相同,与到达跳转指令目标的代码路径无关。您的代码似乎并非如此。一条代码路径似乎到达了一个跳转指令目标,其中一个元素在操作数堆栈上,另一条路径到达了相同的目标语句,堆栈上的元素为零。因此Inconsistent stack height 0 != 1的投诉。

    这个问题很可能与:

    mv.visitJumpInsn(GOTO, endCatchBlock);
    

    我假设验证器抱怨当到达finally 块时,您的异常块在堆栈上的异常引用完成。对于没有抛出异常的路径,情况并非如此。

    尝试删除线

    mv.visitInsn(Opcodes.DUP);
    

    在您的if 语句中,操作数堆栈始终包含零个元素。我假设您让 ASM 为您计算堆栈图帧。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 2021-09-06
      • 1970-01-01
      • 1970-01-01
      • 2017-08-09
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多