解决JVM“函数调用的对象参数不兼容”错误(javassist检测)

Paw*_*lov 2 java jvm javassist

我有 JVM (1.6.0b33) 在我的一个类上抛出 java.lang.VerifyError (函数调用的不兼容对象参数)。使用 javassist(使用 CtMethod.make())对类进行了检测(仅此一种方法)

有没有办法让我找到哪个方法调用触发了错误?我浏览了 javap -c -s -l 的输出,但我没有发现任何调用指令有任何问题。

例如,如果有人知道如何要求 JVM 提供有关检测到此错误的位置的更多详细信息(代码地址会很好)就足够了,所以我知道该关注哪里。如果有人想以这种方式破解它,我可以发布 javap 的输出......

Paw*_*lov 5

在检查 JVM 源代码后弄清楚了。

该错误(函数调用不兼容的对象参数)表示对象进行调用不符合预期(由方法签名)类型(我以为它必须是与对象参数,但你得到一个稍微不同在这种情况下错误)。

显然,当您将一个对象分配给另一个类的对象时,javassist 不会插入正确的指令(或者它可能会使语句失败)。

Javassist 会将以下代码视为有效:

Object x ...;
String s = x; // javac requires cast here, javassist doesn't
s.isEmpty();
Run Code Online (Sandbox Code Playgroud)

通常编译为:

1 aload_1 // push x on stack
2 checkcast java/lang/String // check we can fit x into s
3 astore 2 // s = x;
4 aload 2 // 'this' for isEmpty()
5 invokevirtual String.isEmpty() // stack top used as 'this'
Run Code Online (Sandbox Code Playgroud)

Javassist是(至少版本我有),只是不添加checkcast指令,以及虚拟机有没有保证,在当时invokevirtual被称为堆栈顶部包含字符串,因为需要invokvirtual从String类调用一个方法.

补救办法是:

  • 在赋值中使用显式强制转换
  • 修复javassist
  • 使用显式类型的局部变量