我使用Hibernate运行时类检测。 然而,发生了奇怪的错误:
Caused by: java.lang.VerifyError: Bad type on operand stack in method pkg.model.ValueList$1.<init>(Lpkg/model/ValueList;)V at offset 2
at pkg.model.ValueList.<init>(ValueList.java:24)
我创建了自己的ClassLoader,它应用了转换和 用它来提升整个应用程序。 以下是应用转换的方法:
private byte[] transform(byte[] original) {
for (ClassFileTransformer transformer : transformers) {
try {
byte[] transformed = transformer.transform(this,
className, null, null, original);
if (transformed != null) {
original = transformed;
classReader = new ClassReader(transformed);
try {
CheckClassAdapter.verify(classReader, true,
new PrintWriter(System.out));
} catch (Exception e) {
e.printStackTrace();
}
}
} catch (IllegalClassFormatException e) {
throw new RuntimeException(e);
}
}
return original;
}
我使用此类加载器运行应用程序并获得以下输出:
<init>(Lpkg/model/ValueList;)V
00000 ValueList$1 ValueList : : ALOAD 0
00001 ValueList$1 ValueList : ValueList$1 : ALOAD 1
00002 ValueList$1 ValueList : ValueList$1 ValueList : INVOKEVIRTUAL pkg/model/ValueList$1.$javassist_write_this$0 (Lpkg/model/ValueList;)V
00003 ValueList$1 ValueList : : ALOAD 0
00004 ValueList$1 ValueList : ValueList$1 : INVOKESPECIAL java/util/AbstractList.<init> ()V
00005 ValueList$1 ValueList : : RETURN
我认为偏移2没有错。 我们使用正确的this(ValueList $ 1)和正确的参数(ValueList)调用方法。 并且ASM也没有看到任何不好的事情,因为它的验证者没有例外。 为什么然后JVM验证程序拒绝这个字节码?
Hibernate版本是4.1.10.Final。 以下是与错误相关的代码部分:
public class ValueList {
//...
@Transient
private List<Value> safeValues = new AbstractList<Value>() {
// ...
}
//...
}
答案 0 :(得分:2)
可能是错误消息具有误导性。
您对super()
的调用不是构造函数体中的第一个语句。如果将字节代码转换回Java,它将如下所示:
class ValueListInner extends AbstractList<Value> {
public ValueListInner(ValueList list) {
javassist_write_this_outer(list);
super();
}
private void javassist_write_this_outer(ValueList list) {
//...
}
}
这不是有效的Java代码。 它应该看起来像这样:
<init>(Lpkg/model/ValueList;)V
00000 ValueList$1 ValueList : : ALOAD 0
00001 ValueList$1 ValueList : ValueList$1 : INVOKESPECIAL java/util/AbstractList.<init> ()V
00002 ValueList$1 ValueList : : ALOAD 0
00003 ValueList$1 ValueList : ValueList$1 : ALOAD 1
00004 ValueList$1 ValueList : ValueList$1 ValueList : INVOKEVIRTUAL pkg/model/ValueList$1.$javassist_write_this$0 (Lpkg/model/ValueList;)V
00005 ValueList$1 ValueList : : RETURN