2012-11-05 57 views
0

我开发与ASM的检测引擎,我需要拦截的方法,其中接收阵列类型的参数调用。为此,我实施了MethodVisitor,并在其visitMethodInsn中检查desc参数是否指定了数组类型的任何参数。如果目标方法没有数组类型的参数,那么我无关并且插入原始方法调用:super.visitMethodInsn(opcode, owner, name, desc);如何避免的VerifyError:“希望找到堆栈未初始化对象”的对象已经初始化

另一方面,如果目标方法具有数组类型的参数,那么我必须执行一个针对其论点的具体行动。我获得访问每个参数的最简单的解决方案是调用一个中介方法,具有与目标方法相同的描述符,并且在此介体中,我可以轻松访问其参数(与传递给目标方法的参数相对应)。

然而,当目标方法是一个实例的构造(<init>)出现一个问题。

NEW XXX 
    DUP 
    INVOKESPECIAL XXXX.<init>() 

根据我上面的解释,我移动INVOKESPECIAL呼叫到调解方法和新创建的对象是该中介的第一个参数的方法:在Java的new XXX()如下被翻译成字节码。然而,验证者为这个介体产生一个错误,报告介体的第一个参数(它将成为目标方法的第一个参数 - <init>)不是一个“单元化对象”。更确切地说,我得到了错误:Exception in thread "main" java.lang.VerifyError: Expecting to find unitialized object on stack”

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

任何建议来解决这个问题呢? (请不要回答我避免介体并直接访问堆栈中的参数,因为复制并替换占用堆栈中任意位置的参数并非易事)。

+0

“mediator”方法是什么意思? – vijay

+0

想象一下,在某些时候,我的工具引擎正在拦截目标方法的调用:'obj.foo(x)'。因此,在这一点上,我将这个调用替换为:'obj.foo(x)',by:'mediator $ foo(obj,x)' - 在这种情况下,调解器$ foo是调用方类中的一个新的静态方法。因此,'mediator $ foo(obj,x)'完成它需要的东西,然后调用目标:'obj.foo(x)'。 –

+0

是静态还是实例方法的中介方法? – vijay

回答

1

验证器拒绝您的代码(请参阅JVM规范)。没有办法绕过字节码验证器。

一种方式是围绕在构造函数调用点内联中介代码。在调用构造函数之前或之后,您仍然可以调用调解器的某些部分作为方法调用,但构造函数的调用必须与新指令的方法相同。

另一种方式是让每一个类的实例存在特殊介质,所以调解员调用new指令自己,用构造函数调用一起。

你也可以看看现有的AOP库,如果他们能正确地做必要的工作。