好吧,我有一个Foo
的实例,其中包含一个Object字段obj
,以及一堆其他字段。
我现在创建一个班级Bar
并为其提供Foo
所有的字段以及一些额外的字段。特别是,Bar
也有obj
。
我修改我的课程以使用Bar
代替Foo
,并让他们检测何时提交了Foo
的实例并让他们将其转换为Bar
的实例{1}}(如创建一个包含旧信息的新实例)。
快速检查确认Bar
的新实例具有非空成员obj
。
到目前为止,非常好。
我现在称之为曾使用Foo
的方法,现在使用Bar
。另一项检查确认我们确实使用的是Bar
版本的字节码,而不是旧版本。
查看字节码,我们看到了
getfield Field Foo.obj:"Ljava/lang/Object;";
已更改为
getfield Field Bar.obj:"Ljava/lang/Object;";
然而getfield
正在返回null
。 (或者主要是返回null
,在极少数情况下,它会返回存储在其他字段中的另一个对象,或者甚至在极少数情况下可能会发生段错误。)
对我而言,这看起来像是一个错误的偏移计算。
如果是这样,我应该可以通过将getfield
替换为使用正确偏移的Unsafe.getObject
来绕过此问题。
但在此之前,我想确认这是可能的。 wikipedia表示
该字段由常量池中的字段引用标识
很好,但这并没有告诉我在识别后会发生什么。
Oracle指定
该索引处的运行时常量池项必须是对字段(第5.1节)的符号引用,该字段提供字段的名称和描述符以及字段所在的类的符号引用。被发现。
然后
引用的字段已解决(第5.4.3.2节)。获取objectref中引用字段的值
但即便that paragraph只是说
声明的字段是字段查找的结果。
“抓取”实际上是如何发生的?