java - 如何避免验证错误: “Expecting to find unitialized object on stack” for objects already initialized

标签 java instrumentation java-bytecode-asm

我正在使用 ASM 开发一个仪表引擎,我需要拦截接收数组类型参数的方法的调用。为此,我实现了 MethodVisitor并在其visitMethodInsn中我检查是否 desc参数指定数组类型的任意参数。如果目标方法没有数组类型的参数,那么我什么也不做,我插入原始方法调用:super.visitMethodInsn(opcode, owner, name, desc);

另一方面,如果目标方法具有数组类型的参数,那么我必须对其参数执行特定操作。我访问每个参数的最简单的解决方案是调用一个中介方法,使用与目标方法相同的描述符,并且在这个中介中我可以轻松访问它的参数(对应于传递给目标方法的参数)。

但是,当目标方法是实例构造函数 ( <init> ) 时,就会出现问题。在 Java 中 new XXX()转换为字节码如下:

  NEW XXX 
  DUP 
  INVOKESPECIAL XXXX.<init>()

根据我上面解释的方法,我正在移动 INVOKESPECIAL调用中介方法,新实例化的对象是该中介的第一个参数。然而,验证者会为此中介者引发错误,报告中介者的第一个参数(这将是目标方法的第一个参数 - <init> )不是“统一对象”。更准确地说,我收到错误:Exception in thread "main" java.lang.VerifyError: Expecting to find unitialized object on stack” .

一旦我分割了字节码 NEWINVOKESPECIAL在两种不同的方法中,验证者声称参数传递给 INVOKESPECIAL已经初始化了。

有什么建议可以解决这个问题吗? (请不要回答我以避免中介并直接访问堆栈中的参数,因为复制和替换占据堆栈中任意位置的参数并不简单。)

最佳答案

validator 拒绝您的代码是正确的(请参阅 JVM 规范)。无法绕过字节码 validator 。

一种解决方法是在构造函数调用时内联中介代码。您仍然可以在调用构造函数之前或之后以方法调用的形式调用中介器的一部分,但构造函数调用必须与 new 指令位于同一方法中。

另一种方法是为每个正在实例化的类创建特殊的中介器,因此中介器本身会调用 new 指令以及构造函数调用。

您还可以查看现有的 AOP 库是否可以正确完成所需的工作。

关于java - 如何避免验证错误: “Expecting to find unitialized object on stack” for objects already initialized,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/13234997/

相关文章:

java - 在表中保留最新的 n 个条目

java - 在 Java Applet 中捕获用户的声卡输出

android - 获取资源编号 0xffffffff 的名称时没有已知包

java - Java Instrumentation Agent 是否支持类中的新方法定义?

java - 具有输出值的 ASM Try/Catch block

java - 更新 JLabel 的文本而不改变其他所有内容

java - 将Java中的字符串分解为字符串数组

c# - Visual Studio 2010 在分析报告后进行分析时崩溃

java - 无法从空堆栈中弹出操作数

java - 使用ASM进行字节码分析