在HSDB中查看instanceKlass中vtable的疑问?

JianLeiXing 2014-05-19
首先测试代码如下:
public class Test{
  public static void main(String []args){
    Test test1  = new Test();
  }
}


使用jdb调试让代码停顿到第四行,然后启动HSDB,查找到test1的地址为:0x13fb3070
hsdb> inspect 0x13fb3070
instance of InstanceKlass for Test @ 0x13fb3070 @ 0x13fb3070 (size = 320)
_mark: 1
_metadata._klass: InstanceKlassKlass @ 0x13e20180 Oop @ 0x13e20180
_java_mirror: Oop for java/lang/Class @ 0x03e9faf0 Oop for java/lang/Class @ 0x03e9faf0
_super: InstanceKlass for java/lang/Object @ 0x13e21ae8 Oop @ 0x13e21ae8
_layout_helper: 8
_access_flags: 536870945
_subklass: null null
_next_sibling: InstanceKlass for java/io/FilePermission$1 @ 0x13faf190 Oop @ 0x13faf190
_alloc_count: 0
_array_klasses: null null
_methods: ObjArray @ 0x13fb2f38 Oop for [[I @ 0x13fb2f38
_method_ordering: [I @ 0x13fb3058 Oop for [I @ 0x13fb3058
_local_interfaces: ObjArray @ 0x13e210a8 Oop for [[I @ 0x13e210a8
_transitive_interfaces: ObjArray @ 0x13e210a8 Oop for [[I @ 0x13e210a8
_fields: [S @ 0x13fb2f28 Oop for [S @ 0x13fb2f28
_constants: ConstantPool for Test @ 0x13fb2ea0 Oop @ 0x13fb2ea0
_class_loader: Oop for sun/misc/Launcher$AppClassLoader @ 0x03e93a58 Oop for sun/misc/Launcher$AppClassLoader @ 0x03e93a58
_protection_domain: Oop for java/security/ProtectionDomain @ 0x03e9f660 Oop for java/security/ProtectionDomain @ 0x03e9f660
_signers: null null
_inner_classes: [S @ 0x13e21088 Oop for [S @ 0x13e21088
_nonstatic_field_size: 0
_static_field_size: 0
_static_oop_field_count: 0
_nonstatic_oop_map_size: 0
_is_marked_dependent: 0
_init_state: 5
_vtable_len: 5
_itable_len: 2

根据经验:vtable数据紧帖在InstanceKlass 的最后一个显式C++字段后面。所以只要知道sizeof(instanceKlass),vtable数据就会从这个偏移量开始。 在windows7 x86机器上得知sizeof(instanceKlass)=296(0x128),得知vtable的偏移为:0x13fb3198
然后,获得_vtable和itbable的内存数据
hsdb> mem 0x13fb3198 7
0x13fb3198: 0x13e21670 
0x13fb319c: 0x13e214b0 
0x13fb31a0: 0x13e215c0 
0x13fb31a4: 0x00000000 
0x13fb31a8: 0x00000000 
0x13fb31ac: 0x00000000 
0x13fb31b0: 0x00000001 

发现上述结果不太正确,前三行代表的是java.lang.Object的toString,hashCode和clone方法;丢失了finalize和equal的方法。所以0x13fb3198地址应该向前退2*4个字节即:0x13fb3190
hsdb> mem 0x13fb3190 7
0x13fb3190: 0x13e219d0 
0x13fb3194: 0x13e21540 
0x13fb3198: 0x13e21670 
0x13fb319c: 0x13e214b0 
0x13fb31a0: 0x13e215c0 
0x13fb31a4: 0x00000000 
0x13fb31a8: 0x00000000 

这样就符合:_vtable_len: 5 _itable_len: 2。
vtable:finlize,equal,toString,hashCode,clone
itable:空。

我的疑问是:
1. 为什么sizeof(instanceKlass)=296(0x128)这个偏移不正确?
2. 有什么好的方法可以准确的确定vtable的地址?
RednaxelaFX 2014-05-20
看起来楼主用的是比较32位的新的OpenJDK7u里的HotSpot?请问具体版本是多少?
另外您跑HSDB的环境也是Windows/x86不?
需要更多详细信息才回答得了您的问题。

其实从SA获得的InstanceKlass对象在C++那边看是klassOopDesc,里面包着一个instanceKlass。所以当你算偏移量的时候从SA告诉你的InstanceKlass起始地址开始得加上这么多才行:
align_object_offset(oopDesc::header_size() + sizeof(instanceKlass)/HeapWordSize)

oopDesc::header_size() <- 这是为了klassOopDesc的包装,以HeapWordSize为单位
size。这里在32位HotSpot上会是2。
sizeof(instanceKlass) <- 这是instanceKlass自身的大小,以byte(“一个char的大小”)为单位。后面还除以了HeapWordSize是为了跟oopDesc::header_size()运算。
然后你要byte单位的大小的话就再乘回HeapWordSize就好了。
JianLeiXing 2014-05-20
@RednaxelaFX
感谢R大的回答。

RednaxelaFX 写道
看起来楼主用的是比较32位的新的OpenJDK7u里的HotSpot?请问具体版本是多少?
另外您跑HSDB的环境也是Windows/x86不?
需要更多详细信息才回答得了您的问题。

我的机器信息如下:
Windows 7 Enterprise Service Pack 1 (x86)
JDK版本:
java version "1.7.0_45"
Java(TM) SE Runtime Environment (build 1.7.0_45-b18)
Java HotSpot(TM) Client VM (build 24.45-b08, mixed mode)

HSDB使用的也是上述JDK和机器。


RednaxelaFX 写道

其实从SA获得的InstanceKlass对象在C++那边看是klassOopDesc,里面包着一个instanceKlass。所以当你算偏移量的时候从SA告诉你的InstanceKlass起始地址开始得加上这么多才行:

你说的这个方法我之前也试过,其实就是调用的:instanceKlass::header_size()。获取的值为76,转化为字节为76*4=304(0x130)。该偏移显然过大了。获取的内存数据与设想的不同。

另外,对于像获取sizeof(instanceKlass)这样的数据,有没有相应的工具?是不是只能通过debug源码获得?
Global site tag (gtag.js) - Google Analytics