我正在研究字节码检测项目。目前,在处理对象时,验证程序在大多数情况下都会抛出错误。所以我想清楚地了解有关对象的规则(我阅读了JVMS但找不到我想要的答案):
我正在制定新指令:
原始字节码
NEW <MyClass>
DUP
INVOKESPECIAL <MyClass.<init>>
仪器后
NEW <MyClass>
DUP
INVOKESTATIC <Profiler.handleNEW>
DUP
INVOKESPECIAL <MyClass.<init>>
请注意,我添加了一个对Profiler.handleNEW()的调用,该调用将对象引用(新创建的对象)作为参数。
上面的代码抛出VerificationError。如果我不添加INVOKESTATIC(只留下DUP),它就不会。那么我违反的规则是什么?我可以复制一个未初始化的引用,但我不能将其作为参数传递?我将不胜感激任何帮助。谢谢
答案 0 :(得分:4)
JVM验证程序处理一个尚未被调用构造函数的对象,就好像它有一个名为“uninitialized”的特殊编译时类型。
因此,从验证者的角度来看,您将错误类型的对象作为第一个参数传递给Profiler.handleNEW()
,因为“未初始化”不被视为Object的子类(可以这么说)。
关于如何定义“未初始化”的JVM规范的相关部分是here。
答案 1 :(得分:1)
在调用java.lang.Object
构造函数之前(技术上通常可能退出),引用的类型是“未初始化”。所以在调用构造函数之前,你不能对引用做很多事情。在所讨论的对象的构造函数中也是如此。