[讨论] 怎么查看运行时常量池的数据?

cheney_love 2014-05-11
请教一下:
比如下面的代码:
String a = "a";
String b = "b";
String c  = new String("c");

a , b ,c三个对象对应的值应该都是存在方法区的运行时常量池里面,用HSDB怎么能找到它们呢,在它们所在类的constant pool 和 String 对象的constant pool 里面都没有找到。希望大家能帮忙指点。谢谢
RednaxelaFX 2014-05-12
您的完整代码是怎样的?这很重要。
取决于您的完整代码,找到这些String对象的引用链会不一样。
但如果您这段代码至少执行过一次的话,从StringPool会可以找到它们,然后可以反向找到它们从您的代码出发的引用链(用revptrs)
cheney_love 2014-05-12
RednaxelaFX 写道
您的完整代码是怎样的?这很重要。
取决于您的完整代码,找到这些String对象的引用链会不一样。
但如果您这段代码至少执行过一次的话,从StringPool会可以找到它们,然后可以反向找到它们从您的代码出发的引用链(用revptrs)

谢谢大神回复
public class StringTest {
	public static void main(String args[]){
		String a = "a1";
		String b = "b1";
		String c = a + b;
		String d = new String("ab");
		System.out.println(a + b );
	}
}



比如 String a = "a1"; 中的 "a1",我先用SA 找到了这个对象的地址@0x02c05940
然后用inspect

hsdb> inspect 0x02c05940
instance of "a1" @ 0x02c05940 @ 0x02c05940 (size = 24)
_mark: 1
_metadata._klass: InstanceKlass for java/lang/String @ 0x12b57718 Oop @ 0x12b57718
value: [C @ 0x02c05958 Oop for [C @ 0x02c05958
hash: 0
hash32: 0
hsdb> 


继续 inspect 0x02c05958
hsdb> inspect 0x02c05958
instance of [C @ 0x02c05958 @ 0x02c05958 (size = 16)
_mark: 1
_metadata._klass: TypeArrayKlass for [C @ 0x12b503b8 Oop @ 0x12b503b8
0: 'a'
1: '1'
hsdb> 


我觉得@0x02c05940 应该是a1 在常量池中的地址
然后用 revptrs 0x02c05940
hsdb> revptrs 0x02c05940
Computing reverse pointers...
Done.
null
hsdb> 


现在不明白的是,这个@0x02c05940 到底在哪个地方呢,属于StringTest 的constant pool 还是 String 的constant pool 还是一个单独的constant pool ,怎么能得到这个constant pool 的地址来看看这个 constant pool 的内容呢。
谢谢。
RednaxelaFX 2014-05-13
D:\temp>%JAVA_HOME%\bin\java -cp .;%JAVA_HOME%\lib\sa-jdi.jar sun.jvm.hotspot.CL
HSDB
hsdb> attach 23296
Attaching to process 23296, please wait...
hsdb> class StringTest
StringTest @0x00000000fb077268
hsdb> whatis 0x00000000fb077268
Address 0x00000000fb077268: In perm generation   perm [0x00000000fae00000,0x0000
0000fb077e50,0x00000000fc2c0000) space capacity = 21757952, 11.895604880459338 u
sed
hsdb> inspect 0x00000000fb077268
instance of InstanceKlass for StringTest @ 0x00000000fb077268 @ 0x00000000fb0772
68 (size = 592)
_mark: 1
_java_mirror: Oop for java/lang/Class @ 0x00000000f9ab3940 Oop for java/lang/Cla
ss @ 0x00000000f9ab3940
_super: InstanceKlass for java/lang/Object @ 0x00000000fae02df8 Oop @ 0x00000000
fae02df8
_layout_helper: 16
_access_flags: 538968097
_subklass: null null
_next_sibling: InstanceKlass for java/io/FilePermission$1 @ 0x00000000fb070b38 O
op @ 0x00000000fb070b38
_alloc_count: 0
_array_klasses: null null
_methods: ObjArray @ 0x00000000fb076ff8 Oop for [[I @ 0x00000000fb076ff8
_method_ordering: [I @ 0x00000000fb077250 Oop for [I @ 0x00000000fb077250
_local_interfaces: ObjArray @ 0x00000000fae01d60 Oop for [[I @ 0x00000000fae01d6
0
_transitive_interfaces: ObjArray @ 0x00000000fae01d60 Oop for [[I @ 0x00000000fa
e01d60
_nof_implementors: 0
_implementors[0]: null null
_implementors[0]: null null
_fields: [S @ 0x00000000fb076fe8 Oop for [S @ 0x00000000fb076fe8
_constants: ConstantPool for StringTest @ 0x00000000fb076d88 Oop @ 0x00000000fb0
76d88
_class_loader: Oop for sun/misc/Launcher$AppClassLoader @ 0x00000000f9a8c660 Oop
 for sun/misc/Launcher$AppClassLoader @ 0x00000000f9a8c660
_protection_domain: Oop for java/security/ProtectionDomain @ 0x00000000f9a97ca8
Oop for java/security/ProtectionDomain @ 0x00000000f9a97ca8
_signers: null null
_inner_classes: [S @ 0x00000000fae01d40 Oop for [S @ 0x00000000fae01d40
_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
hsdb> print 0x00000000fb076d88

Constant Pool of [public class StringTest @0x00000000fb077268] @0x00000000fb076d
88

Holder Class
public class StringTest @0x00000000fb077268
Constants
Index Constant Type Constant Value
1 JVM_CONSTANT_Methodref #14 #33
2 JVM_CONSTANT_String "a1"
3 JVM_CONSTANT_String "b1"
4 JVM_CONSTANT_Class public final class java.lang.StringBuilder @0x00000000fae8e
8d0
5 JVM_CONSTANT_Methodref #4 #33
6 JVM_CONSTANT_Methodref #4 #37
7 JVM_CONSTANT_Methodref #4 #38
8 JVM_CONSTANT_Class public final class java.lang.String [signature Ljava/lang/O
bject;Ljava/io/Serializable;Ljava/lang/Comparable<Ljava/lang/String;>;Ljava/lang
/CharSequence;] @0x00000000fae0b8d0
9 JVM_CONSTANT_String "ab"
10 JVM_CONSTANT_Methodref #8 #41
11 JVM_CONSTANT_Fieldref #42 #43
12 JVM_CONSTANT_Methodref #44 #45
13 JVM_CONSTANT_UnresolvedClass StringTest
14 JVM_CONSTANT_UnresolvedClass java/lang/Object
15 JVM_CONSTANT_Utf8 "<init>"
16 JVM_CONSTANT_Utf8 "()V"
17 JVM_CONSTANT_Utf8 "Code"
18 JVM_CONSTANT_Utf8 "LineNumberTable"
19 JVM_CONSTANT_Utf8 "LocalVariableTable"
20 JVM_CONSTANT_Utf8 "this"
21 JVM_CONSTANT_Utf8 "LStringTest;"
22 JVM_CONSTANT_Utf8 "main"
23 JVM_CONSTANT_Utf8 "([Ljava/lang/String;)V"
24 JVM_CONSTANT_Utf8 "args"
25 JVM_CONSTANT_Utf8 "[Ljava/lang/String;"
26 JVM_CONSTANT_Utf8 "a"
27 JVM_CONSTANT_Utf8 "Ljava/lang/String;"
28 JVM_CONSTANT_Utf8 "b"
29 JVM_CONSTANT_Utf8 "c"
30 JVM_CONSTANT_Utf8 "d"
31 JVM_CONSTANT_Utf8 "SourceFile"
32 JVM_CONSTANT_Utf8 "StringTest.java"
33 JVM_CONSTANT_NameAndType #15 #16
34 JVM_CONSTANT_Utf8 "a1"
35 JVM_CONSTANT_Utf8 "b1"
36 JVM_CONSTANT_Utf8 "java/lang/StringBuilder"
37 JVM_CONSTANT_NameAndType #48 #49
38 JVM_CONSTANT_NameAndType #50 #51
39 JVM_CONSTANT_Utf8 "java/lang/String"
40 JVM_CONSTANT_Utf8 "ab"
41 JVM_CONSTANT_NameAndType #15 #52
42 JVM_CONSTANT_UnresolvedClass java/lang/System
43 JVM_CONSTANT_NameAndType #54 #55
44 JVM_CONSTANT_UnresolvedClass java/io/PrintStream
45 JVM_CONSTANT_NameAndType #57 #52
46 JVM_CONSTANT_Utf8 "StringTest"
47 JVM_CONSTANT_Utf8 "java/lang/Object"
48 JVM_CONSTANT_Utf8 "append"
49 JVM_CONSTANT_Utf8 "(Ljava/lang/String;)Ljava/lang/StringBuilder;"
50 JVM_CONSTANT_Utf8 "toString"
51 JVM_CONSTANT_Utf8 "()Ljava/lang/String;"
52 JVM_CONSTANT_Utf8 "(Ljava/lang/String;)V"
53 JVM_CONSTANT_Utf8 "java/lang/System"
54 JVM_CONSTANT_Utf8 "out"
55 JVM_CONSTANT_Utf8 "Ljava/io/PrintStream;"
56 JVM_CONSTANT_Utf8 "java/io/PrintStream"
57 JVM_CONSTANT_Utf8 "println"


hsdb> jseval "st = sa.vm.stringTable"
sun.jvm.hotspot.memory.StringTable@0x000000000246adc0
hsdb> jseval "st.stringsDo(function (s) { if (sapkg.oops.OopUtilities.stringOopToString(s).matches('^(a|b).')) {print(s + ': '); s.printValueOn(java.lang.System.out); println('')}})"
sun.jvm.hotspot.oops.Instance@f9ab3c70: "a1"
sun.jvm.hotspot.oops.Instance@f9ab3ca0: "b1"
sun.jvm.hotspot.oops.Instance@f9ab3fe0: "ab"
sun.jvm.hotspot.oops.Instance@f9a83400: "az"
hsdb> revptrs 0x0f9ab3c70
null
hsdb> revptrs 0x0f9ab3ca0
null
hsdb> revptrs 0x0f9ab3fe0
no live references to 0x00000000f9ab3fe0
hsdb> jseval "java.lang.Long.toHexString(0x00000000fb076d88+sapkg.oops.ConstantPool.headerSize*4)"
fb076dc8
hsdb> mem 0xfb076dc8 10
0x00000000fb076dc8: 0x0000000000000000
0x00000000fb076dd0: 0x000000000021000e
0x00000000fb076dd8: 0x00000000f9ab3c70   => "a1"
0x00000000fb076de0: 0x00000000f9ab3ca0   => "b1"
0x00000000fb076de8: 0x00000000fae8e8d0
0x00000000fb076df0: 0x0000000000210004
0x00000000fb076df8: 0x0000000000250004
0x00000000fb076e00: 0x0000000000260004
0x00000000fb076e08: 0x00000000fae0b8d0
0x00000000fb076e10: 0x00000000f9ab3fe0   => "ab"

hsdb> whatis 0x0f9ab3c70
Address 0x00000000f9ab3c70: In thread-local allocation buffer for thread "main"
(1)  [0x00000000f9ab3668,0x00000000f9ab4010,0x00000000f9aceed8)

hsdb> whatis 0xf9ab3ca0
Address 0x00000000f9ab3ca0: In thread-local allocation buffer for thread "main"
(1)  [0x00000000f9ab3668,0x00000000f9ab4010,0x00000000f9aceed8)

hsdb> whatis 0xf9ab3fe0
Address 0x00000000f9ab3fe0: In thread-local allocation buffer for thread "main"
(1)  [0x00000000f9ab3668,0x00000000f9ab4010,0x00000000f9aceed8)

hsdb>

先发这个给楼主看。楼主能自己找到规律不?
cheney_love 2014-05-16
RednaxelaFX 写道
D:\temp>%JAVA_HOME%\bin\java -cp .;%JAVA_HOME%\lib\sa-jdi.jar sun.jvm.hotspot.CL
HSDB
hsdb> attach 23296
Attaching to process 23296, please wait...
hsdb> class StringTest
StringTest @0x00000000fb077268
hsdb> whatis 0x00000000fb077268
Address 0x00000000fb077268: In perm generation   perm [0x00000000fae00000,0x0000
0000fb077e50,0x00000000fc2c0000) space capacity = 21757952, 11.895604880459338 u
sed
hsdb> inspect 0x00000000fb077268
instance of InstanceKlass for StringTest @ 0x00000000fb077268 @ 0x00000000fb0772
68 (size = 592)
_mark: 1
_java_mirror: Oop for java/lang/Class @ 0x00000000f9ab3940 Oop for java/lang/Cla
ss @ 0x00000000f9ab3940
_super: InstanceKlass for java/lang/Object @ 0x00000000fae02df8 Oop @ 0x00000000
fae02df8
_layout_helper: 16
_access_flags: 538968097
_subklass: null null
_next_sibling: InstanceKlass for java/io/FilePermission$1 @ 0x00000000fb070b38 O
op @ 0x00000000fb070b38
_alloc_count: 0
_array_klasses: null null
_methods: ObjArray @ 0x00000000fb076ff8 Oop for [[I @ 0x00000000fb076ff8
_method_ordering: [I @ 0x00000000fb077250 Oop for [I @ 0x00000000fb077250
_local_interfaces: ObjArray @ 0x00000000fae01d60 Oop for [[I @ 0x00000000fae01d6
0
_transitive_interfaces: ObjArray @ 0x00000000fae01d60 Oop for [[I @ 0x00000000fa
e01d60
_nof_implementors: 0
_implementors[0]: null null
_implementors[0]: null null
_fields: [S @ 0x00000000fb076fe8 Oop for [S @ 0x00000000fb076fe8
_constants: ConstantPool for StringTest @ 0x00000000fb076d88 Oop @ 0x00000000fb0
76d88
_class_loader: Oop for sun/misc/Launcher$AppClassLoader @ 0x00000000f9a8c660 Oop
 for sun/misc/Launcher$AppClassLoader @ 0x00000000f9a8c660
_protection_domain: Oop for java/security/ProtectionDomain @ 0x00000000f9a97ca8
Oop for java/security/ProtectionDomain @ 0x00000000f9a97ca8
_signers: null null
_inner_classes: [S @ 0x00000000fae01d40 Oop for [S @ 0x00000000fae01d40
_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
hsdb> print 0x00000000fb076d88

Constant Pool of [public class StringTest @0x00000000fb077268] @0x00000000fb076d
88

Holder Class
public class StringTest @0x00000000fb077268
Constants
Index Constant Type Constant Value
1 JVM_CONSTANT_Methodref #14 #33
2 JVM_CONSTANT_String "a1"
3 JVM_CONSTANT_String "b1"
4 JVM_CONSTANT_Class public final class java.lang.StringBuilder @0x00000000fae8e
8d0
5 JVM_CONSTANT_Methodref #4 #33
6 JVM_CONSTANT_Methodref #4 #37
7 JVM_CONSTANT_Methodref #4 #38
8 JVM_CONSTANT_Class public final class java.lang.String [signature Ljava/lang/O
bject;Ljava/io/Serializable;Ljava/lang/Comparable<Ljava/lang/String;>;Ljava/lang
/CharSequence;] @0x00000000fae0b8d0
9 JVM_CONSTANT_String "ab"
10 JVM_CONSTANT_Methodref #8 #41
11 JVM_CONSTANT_Fieldref #42 #43
12 JVM_CONSTANT_Methodref #44 #45
13 JVM_CONSTANT_UnresolvedClass StringTest
14 JVM_CONSTANT_UnresolvedClass java/lang/Object
15 JVM_CONSTANT_Utf8 "<init>"
16 JVM_CONSTANT_Utf8 "()V"
17 JVM_CONSTANT_Utf8 "Code"
18 JVM_CONSTANT_Utf8 "LineNumberTable"
19 JVM_CONSTANT_Utf8 "LocalVariableTable"
20 JVM_CONSTANT_Utf8 "this"
21 JVM_CONSTANT_Utf8 "LStringTest;"
22 JVM_CONSTANT_Utf8 "main"
23 JVM_CONSTANT_Utf8 "([Ljava/lang/String;)V"
24 JVM_CONSTANT_Utf8 "args"
25 JVM_CONSTANT_Utf8 "[Ljava/lang/String;"
26 JVM_CONSTANT_Utf8 "a"
27 JVM_CONSTANT_Utf8 "Ljava/lang/String;"
28 JVM_CONSTANT_Utf8 "b"
29 JVM_CONSTANT_Utf8 "c"
30 JVM_CONSTANT_Utf8 "d"
31 JVM_CONSTANT_Utf8 "SourceFile"
32 JVM_CONSTANT_Utf8 "StringTest.java"
33 JVM_CONSTANT_NameAndType #15 #16
34 JVM_CONSTANT_Utf8 "a1"
35 JVM_CONSTANT_Utf8 "b1"
36 JVM_CONSTANT_Utf8 "java/lang/StringBuilder"
37 JVM_CONSTANT_NameAndType #48 #49
38 JVM_CONSTANT_NameAndType #50 #51
39 JVM_CONSTANT_Utf8 "java/lang/String"
40 JVM_CONSTANT_Utf8 "ab"
41 JVM_CONSTANT_NameAndType #15 #52
42 JVM_CONSTANT_UnresolvedClass java/lang/System
43 JVM_CONSTANT_NameAndType #54 #55
44 JVM_CONSTANT_UnresolvedClass java/io/PrintStream
45 JVM_CONSTANT_NameAndType #57 #52
46 JVM_CONSTANT_Utf8 "StringTest"
47 JVM_CONSTANT_Utf8 "java/lang/Object"
48 JVM_CONSTANT_Utf8 "append"
49 JVM_CONSTANT_Utf8 "(Ljava/lang/String;)Ljava/lang/StringBuilder;"
50 JVM_CONSTANT_Utf8 "toString"
51 JVM_CONSTANT_Utf8 "()Ljava/lang/String;"
52 JVM_CONSTANT_Utf8 "(Ljava/lang/String;)V"
53 JVM_CONSTANT_Utf8 "java/lang/System"
54 JVM_CONSTANT_Utf8 "out"
55 JVM_CONSTANT_Utf8 "Ljava/io/PrintStream;"
56 JVM_CONSTANT_Utf8 "java/io/PrintStream"
57 JVM_CONSTANT_Utf8 "println"


hsdb> jseval "st = sa.vm.stringTable"
sun.jvm.hotspot.memory.StringTable@0x000000000246adc0
hsdb> jseval "st.stringsDo(function (s) { if (sapkg.oops.OopUtilities.stringOopToString(s).matches('^(a|b).')) {print(s + ': '); s.printValueOn(java.lang.System.out); println('')}})"
sun.jvm.hotspot.oops.Instance@f9ab3c70: "a1"
sun.jvm.hotspot.oops.Instance@f9ab3ca0: "b1"
sun.jvm.hotspot.oops.Instance@f9ab3fe0: "ab"
sun.jvm.hotspot.oops.Instance@f9a83400: "az"
hsdb> revptrs 0x0f9ab3c70
null
hsdb> revptrs 0x0f9ab3ca0
null
hsdb> revptrs 0x0f9ab3fe0
no live references to 0x00000000f9ab3fe0
hsdb> jseval "java.lang.Long.toHexString(0x00000000fb076d88+sapkg.oops.ConstantPool.headerSize*4)"
fb076dc8
hsdb> mem 0xfb076dc8 10
0x00000000fb076dc8: 0x0000000000000000
0x00000000fb076dd0: 0x000000000021000e
0x00000000fb076dd8: 0x00000000f9ab3c70   => "a1"
0x00000000fb076de0: 0x00000000f9ab3ca0   => "b1"
0x00000000fb076de8: 0x00000000fae8e8d0
0x00000000fb076df0: 0x0000000000210004
0x00000000fb076df8: 0x0000000000250004
0x00000000fb076e00: 0x0000000000260004
0x00000000fb076e08: 0x00000000fae0b8d0
0x00000000fb076e10: 0x00000000f9ab3fe0   => "ab"

hsdb> whatis 0x0f9ab3c70
Address 0x00000000f9ab3c70: In thread-local allocation buffer for thread "main"
(1)  [0x00000000f9ab3668,0x00000000f9ab4010,0x00000000f9aceed8)

hsdb> whatis 0xf9ab3ca0
Address 0x00000000f9ab3ca0: In thread-local allocation buffer for thread "main"
(1)  [0x00000000f9ab3668,0x00000000f9ab4010,0x00000000f9aceed8)

hsdb> whatis 0xf9ab3fe0
Address 0x00000000f9ab3fe0: In thread-local allocation buffer for thread "main"
(1)  [0x00000000f9ab3668,0x00000000f9ab4010,0x00000000f9aceed8)

hsdb>

先发这个给楼主看。楼主能自己找到规律不?

谢谢大神耐心讲解,这几天看了sa.js 然后又以sa.js 里面的一些对象为线索看了一下和sa 相关的java 源代码,
总算是对内存结构有了一点认识。
我在运行您给的例子的时候,遇到了几个问题,希望大神能抽空指导一下:
1. 第一个疑问:
jseval "java.lang.Long.toHexString(0x00000000fb076d88+sapkg.oops.ConstantPool.headerSize*4)" 

  这个headerSize*4 是什么意思呢,我按照这个方法运行,得到计算结果后,用 mem 0xfb076dc8 10 得出的结果里面不包含
那几个变量是怎么回事。我测试的jvm版本分别是“Java(TM) SE Runtime Environment (build 1.7.0_51-b13)“ 和 ”build 1.6.0_25-fastdebug“
例如:
class Test2
Test2 @0x000000010f405018

inspect 0x000000010f405018
instance of InstanceKlass for Test2 @ 0x000000010f405018 @ 0x000000010f405018 (size = 552)
_mark: 1
_java_mirror: Oop for java/lang/Class @ 0x00000001699e1d70 Oop for java/lang/Class @ 0x00000001699e1d70
_super: InstanceKlass for java/lang/Object @ 0x000000010f182bb0 Oop @ 0x000000010f182bb0
_layout_helper: 16
_access_flags: 538968097
_subklass: null null
_next_sibling: InstanceKlass for java/io/FilePermission$1 @ 0x000000010f3fea30 Oop @ 0x000000010f3fea30
_alloc_count: 0
_array_klasses: null null
_methods: ObjArray @ 0x000000010f404be8 Oop for [[I @ 0x000000010f404be8
_method_ordering: [I @ 0x000000010f404ff8 Oop for [I @ 0x000000010f404ff8
_local_interfaces: ObjArray @ 0x000000010f181bf8 Oop for [[I @ 0x000000010f181bf8
_transitive_interfaces: ObjArray @ 0x000000010f181bf8 Oop for [[I @ 0x000000010f181bf8
_fields: [S @ 0x000000010f404bd8 Oop for [S @ 0x000000010f404bd8
_constants: ConstantPool for Test2 @ 0x000000010f4048a0 Oop @ 0x000000010f4048a0
_class_loader: Oop for sun/misc/Launcher$AppClassLoader @ 0x00000001698da688 Oop for sun/misc/Launcher$AppClassLoader @ 0x00000001698da688
_protection_domain: Oop for java/security/ProtectionDomain @ 0x00000001699e1830 Oop for java/security/ProtectionDomain @ 0x00000001699e1830
_signers: null null
_inner_classes: [S @ 0x000000010f181bd8 Oop for [S @ 0x000000010f181bd8
_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

jseval "st = sa.vm.stringTable"
sun.jvm.hotspot.memory.StringTable@0x00007ff5ca60e970

jseval "st.stringsDo(function (s) { if (sapkg.oops.OopUtilities.stringOopToString(s).matches('^(a|b).')) {print(s + ': '); s.printValueOn(java.lang.System.out); println('')}})"
sun.jvm.hotspot.oops.Instance@699e2398: "a1"
sun.jvm.hotspot.oops.Instance@699e23c8: "b1"
sun.jvm.hotspot.oops.Instance@699e23f8: "ab"
sun.jvm.hotspot.oops.Instance@698dfc68: "az"

jseval "java.lang.Long.toHexString(0x000000010f4048a0+sapkg.oops.ConstantPool.headerSize*4)"
10f4048e0
mem 0x10f4048e0 10
0x000000010f4048e0: 0x0000000000000000 
0x000000010f4048e8: 0x00007ff5ca626681 
0x000000010f4048f0: 0x00007ff5ca626681 
0x000000010f4048f8: 0x000000010f182bb0 
0x000000010f404900: 0x00000001995420c1 
0x000000010f404908: 0x0000000199544491 
0x000000010f404910: 0x0000000199545ec1 
0x000000010f404918: 0x0000000199542b21 
0x000000010f404920: 0x00000000000b0009 
0x000000010f404928: 0x000000010f1a09d0

木有那几个变量,为什么?
 


2.第二个疑问:
jseval "st.stringsDo(function (s) { if (sapkg.oops.OopUtilities.stringOopToString(s).matches('^(a|b).')) {print(s + ': '); s.printValueOn(java.lang.System.out); println('')}})"

这句话,我找到了StringTable 的这个方法
public void More ...stringsDo(StringVisitor visitor) {
    ObjectHeap oh = VM.getVM().getObjectHeap();
    int numBuckets = tableSize();
    for (int i = 0; i < numBuckets; i++) {
      for (HashtableEntry e = (HashtableEntry) bucket(i); e != null;
           e = (HashtableEntry) e.next()) {
        Instance s = (Instance)oh.newOop(e.literalValue().addOffsetToAsOopHandle(0));
        visitor.visit(s);
      }
    }

这里应该传入一个StringVisitor,为什么您传入一个别的对象也可以执行呢?

谢谢大神。
RednaxelaFX 2014-05-17
cheney_love 写道
谢谢大神耐心讲解,这几天看了sa.js 然后又以sa.js 里面的一些对象为线索看了一下和sa 相关的java 源代码,
总算是对内存结构有了一点认识。

能说说有了怎样的认识不?分享一下让后来人更容易找到资料

回答问题1:请楼主把Test2的完整代码发一下。看这种东西的时候细节很重要。

另外把您的Test2的javap -v的输出也发一下。这是用来确定您要找的常量在您编译得到的Class文件里到底在哪些index。

然后再对比一下您在CLHSDB里用print <constant pool address>看到的内容。

回答问题2:因为这里用的是JavaScript而不是Java
JDK自带的Java实现 ,无论是JDK6、JDK7的Rhino还是JDK8的Nashorn,都带有一个叫做JavaAdapter的东西,可以自动把JavaScript对象包装成合适的Java对象传给Java代码。这里,我是把一个JavaScript函数传给了一个只有单一抽象方法的接口,Rhino/Nashorn的JavaAdapter就自动帮我实现了那个接口并且让那个抽象方法的实现调用我传入的函数。超方便。
cheney_love 2014-05-17
RednaxelaFX 写道

能说说有了怎样的认识不?分享一下让后来人更容易找到资料

谢谢大神指点,等弄明白了这里,我就好好的理一理然后写篇感受,让其他的新入门的朋友多一份参考。

我改成了最开始的StringTest类

public class StringTest {
	public static void main(String args[]){
		String a = "a1";
		String b = "b1";
		String c = a + b;
		String d = new String("ab");
		System.out.println(a + b );
	}
}



1.javap 代码
Compiled from "StringTest.java"
public class StringTest extends java.lang.Object
  SourceFile: "StringTest.java"
  minor version: 0
  major version: 51
  Constant pool:
const #1 = class #2; //  StringTest
const #2 = Asciz StringTest;
const #3 = class #4; //  java/lang/Object
const #4 = Asciz java/lang/Object;
const #5 = Asciz <init>;
const #6 = Asciz ()V;
const #7 = Asciz Code;
const #8 = Method #3.#9; //  java/lang/Object."<init>":()V
const #9 = NameAndType #5:#6;//  "<init>":()V
const #10 = Asciz LineNumberTable;
const #11 = Asciz LocalVariableTable;
const #12 = Asciz this;
const #13 = Asciz LStringTest;;
const #14 = Asciz main;
const #15 = Asciz ([Ljava/lang/String;)V;
const #16 = String #17; //  a1
const #17 = Asciz a1;
const #18 = String #19; //  b1
const #19 = Asciz b1;
const #20 = class #21; //  java/lang/StringBuilder
const #21 = Asciz java/lang/StringBuilder;
const #22 = Method #23.#25; //  java/lang/String.valueOf:(Ljava/lang/Object;)Ljava/lang/String;
const #23 = class #24; //  java/lang/String
const #24 = Asciz java/lang/String;
const #25 = NameAndType #26:#27;//  valueOf:(Ljava/lang/Object;)Ljava/lang/String;
const #26 = Asciz valueOf;
const #27 = Asciz (Ljava/lang/Object;)Ljava/lang/String;;
const #28 = Method #20.#29; //  java/lang/StringBuilder."<init>":(Ljava/lang/String;)V
const #29 = NameAndType #5:#30;//  "<init>":(Ljava/lang/String;)V
const #30 = Asciz (Ljava/lang/String;)V;
const #31 = Method #20.#32; //  java/lang/StringBuilder.append:(Ljava/lang/String;)Ljava/lang/StringBuilder;
const #32 = NameAndType #33:#34;//  append:(Ljava/lang/String;)Ljava/lang/StringBuilder;
const #33 = Asciz append;
const #34 = Asciz (Ljava/lang/String;)Ljava/lang/StringBuilder;;
const #35 = Method #20.#36; //  java/lang/StringBuilder.toString:()Ljava/lang/String;
const #36 = NameAndType #37:#38;//  toString:()Ljava/lang/String;
const #37 = Asciz toString;
const #38 = Asciz ()Ljava/lang/String;;
const #39 = String #40; //  ab
const #40 = Asciz ab;
const #41 = Method #23.#29; //  java/lang/String."<init>":(Ljava/lang/String;)V
const #42 = Field #43.#45; //  java/lang/System.out:Ljava/io/PrintStream;
const #43 = class #44; //  java/lang/System
const #44 = Asciz java/lang/System;
const #45 = NameAndType #46:#47;//  out:Ljava/io/PrintStream;
const #46 = Asciz out;
const #47 = Asciz Ljava/io/PrintStream;;
const #48 = Method #49.#51; //  java/io/PrintStream.println:(Ljava/lang/String;)V
const #49 = class #50; //  java/io/PrintStream
const #50 = Asciz java/io/PrintStream;
const #51 = NameAndType #52:#30;//  println:(Ljava/lang/String;)V
const #52 = Asciz println;
const #53 = Asciz args;
const #54 = Asciz [Ljava/lang/String;;
const #55 = Asciz a;
const #56 = Asciz Ljava/lang/String;;
const #57 = Asciz b;
const #58 = Asciz c;
const #59 = Asciz d;
const #60 = Asciz SourceFile;
const #61 = Asciz StringTest.java;

{
public StringTest();
  Code:
   Stack=1, Locals=1, Args_size=1
   0: aload_0
   1: invokespecial #8; //Method java/lang/Object."<init>":()V
   4: return
  LineNumberTable:
   line 1: 0

  LocalVariableTable:
   Start  Length  Slot  Name   Signature
   0      5      0    this       LStringTest;


public static void main(java.lang.String[]);
  Code:
   Stack=4, Locals=5, Args_size=1
   0: ldc #16; //String a1
   2: astore_1
   3: ldc #18; //String b1
   5: astore_2
   6: new #20; //class java/lang/StringBuilder
   9: dup
   10: aload_1
   11: invokestatic #22; //Method java/lang/String.valueOf:(Ljava/lang/Object;)Ljava/lang/String;
   14: invokespecial #28; //Method java/lang/StringBuilder."<init>":(Ljava/lang/String;)V
   17: aload_2
   18: invokevirtual #31; //Method java/lang/StringBuilder.append:(Ljava/lang/String;)Ljava/lang/StringBuilder;
   21: invokevirtual #35; //Method java/lang/StringBuilder.toString:()Ljava/lang/String;
   24: astore_3
   25: new #23; //class java/lang/String
   28: dup
   29: ldc #39; //String ab
   31: invokespecial #41; //Method java/lang/String."<init>":(Ljava/lang/String;)V
   34: astore 4
   36: getstatic #42; //Field java/lang/System.out:Ljava/io/PrintStream;
   39: new #20; //class java/lang/StringBuilder
   42: dup
   43: aload_1
   44: invokestatic #22; //Method java/lang/String.valueOf:(Ljava/lang/Object;)Ljava/lang/String;
   47: invokespecial #28; //Method java/lang/StringBuilder."<init>":(Ljava/lang/String;)V
   50: aload_2
   51: invokevirtual #31; //Method java/lang/StringBuilder.append:(Ljava/lang/String;)Ljava/lang/StringBuilder;
   54: invokevirtual #35; //Method java/lang/StringBuilder.toString:()Ljava/lang/String;
   57: invokevirtual #48; //Method java/io/PrintStream.println:(Ljava/lang/String;)V
   60: return
  LineNumberTable:
   line 3: 0
   line 4: 3
   line 5: 6
   line 6: 25
   line 7: 36
   line 8: 60

  LocalVariableTable:
   Start  Length  Slot  Name   Signature
   0      61      0    args       [Ljava/lang/String;
   3      58      1    a       Ljava/lang/String;
   6      55      2    b       Ljava/lang/String;
   25      36      3    c       Ljava/lang/String;
   36      25      4    d       Ljava/lang/String;


}



1.CLHSDB 代码

hsdb> attach 4347
Attaching to process 4347, please wait...
hsdb> class StringTest
StringTest @0x000000077b084d80
hsdb> inspect 0x000000077b084d80
instance of InstanceKlass for StringTest @ 0x000000077b084d80 @ 0x000000077b084d80 (size = 552)
_mark: 1
_java_mirror: Oop for java/lang/Class @ 0x00000007d5661820 Oop for java/lang/Class @ 0x00000007d5661820
_super: InstanceKlass for java/lang/Object @ 0x000000077ae02bb0 Oop @ 0x000000077ae02bb0
_layout_helper: 16
_access_flags: 538968097
_subklass: null null
_next_sibling: InstanceKlass for java/io/FilePermission$1 @ 0x000000077b07ea30 Oop @ 0x000000077b07ea30
_alloc_count: 0
_array_klasses: null null
_methods: ObjArray @ 0x000000077b084b30 Oop for [[I @ 0x000000077b084b30
_method_ordering: [I @ 0x000000077b084d68 Oop for [I @ 0x000000077b084d68
_local_interfaces: ObjArray @ 0x000000077ae01bf8 Oop for [[I @ 0x000000077ae01bf8
_transitive_interfaces: ObjArray @ 0x000000077ae01bf8 Oop for [[I @ 0x000000077ae01bf8
_fields: [S @ 0x000000077b084b20 Oop for [S @ 0x000000077b084b20
_constants: ConstantPool for StringTest @ 0x000000077b0848a0 Oop @ 0x000000077b0848a0
_class_loader: Oop for sun/misc/Launcher$AppClassLoader @ 0x00000007d555a698 Oop for sun/misc/Launcher$AppClassLoader @ 0x00000007d555a698
_protection_domain: Oop for java/security/ProtectionDomain @ 0x00000007d56612e0 Oop for java/security/ProtectionDomain @ 0x00000007d56612e0
_signers: null null
_inner_classes: [S @ 0x000000077ae01bd8 Oop for [S @ 0x000000077ae01bd8
_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
hsdb> print 0x000000077b0848a0

Constant Pool of [public class StringTest @0x000000077b084d80] @0x000000077b0848a0

Holder Class
public class StringTest @0x000000077b084d80
Constants
Index Constant Type Constant Value
1 JVM_CONSTANT_UnresolvedClass StringTest
2 JVM_CONSTANT_Utf8 "StringTest"
3 JVM_CONSTANT_UnresolvedClass java/lang/Object
4 JVM_CONSTANT_Utf8 "java/lang/Object"
5 JVM_CONSTANT_Utf8 "<init>"
6 JVM_CONSTANT_Utf8 "()V"
7 JVM_CONSTANT_Utf8 "Code"
8 JVM_CONSTANT_Methodref #3 #9
9 JVM_CONSTANT_NameAndType #5 #6
10 JVM_CONSTANT_Utf8 "LineNumberTable"
11 JVM_CONSTANT_Utf8 "LocalVariableTable"
12 JVM_CONSTANT_Utf8 "this"
13 JVM_CONSTANT_Utf8 "LStringTest;"
14 JVM_CONSTANT_Utf8 "main"
15 JVM_CONSTANT_Utf8 "([Ljava/lang/String;)V"
16 JVM_CONSTANT_String "a1"
17 JVM_CONSTANT_Utf8 "a1"
18 JVM_CONSTANT_String "b1"
19 JVM_CONSTANT_Utf8 "b1"
20 JVM_CONSTANT_Class public final class java.lang.StringBuilder @0x000000077ae89658
21 JVM_CONSTANT_Utf8 "java/lang/StringBuilder"
22 JVM_CONSTANT_Methodref #23 #25
23 JVM_CONSTANT_Class public final class java.lang.String [signature Ljava/lang/Object;Ljava/io/Serializable;Ljava/lang/Comparable<Ljava/lang/String;>;Ljava/lang/CharSequence;] @0x000000077ae0b028
24 JVM_CONSTANT_Utf8 "java/lang/String"
25 JVM_CONSTANT_NameAndType #26 #27
26 JVM_CONSTANT_Utf8 "valueOf"
27 JVM_CONSTANT_Utf8 "(Ljava/lang/Object;)Ljava/lang/String;"
28 JVM_CONSTANT_Methodref #20 #29
29 JVM_CONSTANT_NameAndType #5 #30
30 JVM_CONSTANT_Utf8 "(Ljava/lang/String;)V"
31 JVM_CONSTANT_Methodref #20 #32
32 JVM_CONSTANT_NameAndType #33 #34
33 JVM_CONSTANT_Utf8 "append"
34 JVM_CONSTANT_Utf8 "(Ljava/lang/String;)Ljava/lang/StringBuilder;"
35 JVM_CONSTANT_Methodref #20 #36
36 JVM_CONSTANT_NameAndType #37 #38
37 JVM_CONSTANT_Utf8 "toString"
38 JVM_CONSTANT_Utf8 "()Ljava/lang/String;"
39 JVM_CONSTANT_String "ab"
40 JVM_CONSTANT_Utf8 "ab"
41 JVM_CONSTANT_Methodref #23 #29
42 JVM_CONSTANT_Fieldref #43 #45
43 JVM_CONSTANT_UnresolvedClass java/lang/System
44 JVM_CONSTANT_Utf8 "java/lang/System"
45 JVM_CONSTANT_NameAndType #46 #47
46 JVM_CONSTANT_Utf8 "out"
47 JVM_CONSTANT_Utf8 "Ljava/io/PrintStream;"
48 JVM_CONSTANT_Methodref #49 #51
49 JVM_CONSTANT_UnresolvedClass java/io/PrintStream
50 JVM_CONSTANT_Utf8 "java/io/PrintStream"
51 JVM_CONSTANT_NameAndType #52 #30
52 JVM_CONSTANT_Utf8 "println"
53 JVM_CONSTANT_Utf8 "args"
54 JVM_CONSTANT_Utf8 "[Ljava/lang/String;"
55 JVM_CONSTANT_Utf8 "a"
56 JVM_CONSTANT_Utf8 "Ljava/lang/String;"
57 JVM_CONSTANT_Utf8 "b"
58 JVM_CONSTANT_Utf8 "c"
59 JVM_CONSTANT_Utf8 "d"
60 JVM_CONSTANT_Utf8 "SourceFile"
61 JVM_CONSTANT_Utf8 "StringTest.java"


hsdb>  jseval "st = sa.vm.stringTable"
sun.jvm.hotspot.memory.StringTable@0x00007ffa7141ce70
hsdb> jseval "st.stringsDo(function (s) { if (sapkg.oops.OopUtilities.stringOopToString(s).matches('^(a|b).')) {print(s + ': '); s.printValueOn(java.lang.System.out); println('')}})"
sun.jvm.hotspot.oops.Instance@d5661b50: "a1"
sun.jvm.hotspot.oops.Instance@d5661b80: "b1"
sun.jvm.hotspot.oops.Instance@d5661ec8: "ab"
sun.jvm.hotspot.oops.Instance@d555fca0: "az"
hsdb> revptrs 0x0d5661b50
Computing reverse pointers...
Done.
hsdb> revptrs 0x0d5661b80
hsdb> revptrs 0x0d5661ec8
hsdb> jseval "java.lang.Long.toHexString(0x000000077b084d80+sapkg.oops.ConstantPool.headerSize*4)"
77b084dc0
hsdb> mem 0x77b084dc0 10
0x000000077b084dc0: 0x000000077b084d80
0x000000077b084dc8: 0x0000000000000000
0x000000077b084dd0: 0x0000000000000000
0x000000077b084dd8: 0x0000000000000000
0x000000077b084de0: 0x0000000000000000
0x000000077b084de8: 0x0000000000000000
0x000000077b084df0: 0x0000000000000000
0x000000077b084df8: 0x00000007d5661820
0x000000077b084e00: 0x000000077ae02bb0
0x000000077b084e08: 0x0000000000000000

这里为什么没有上面的变量呢?,和jdk版本有关系吗,我的是
MacOS java version "1.7.0_51"
Java(TM) SE Runtime Environment (build 1.7.0_51-b13)
Java HotSpot(TM) 64-Bit Server VM (build 24.51-b03, mixed mode)

还一个奇怪的地方:
hsdb> whatis 0xd5661b50
Address 0x00000000d5661b50: In unknown location
在ubuntu jdk1.6  fastdebug 版本上可以显示位于方法区


谢谢大神指点。
RednaxelaFX 2014-05-17
那是因为楼主提供的日志显示,您的Class文件里您关心的那几个String常量位于常量池更靠后的位置(例如"a1"的index是16)而我的Class文件里它位于更前的位置(例如"a1"的index是2),所以我只需要打印constantPoolOopDesc里常量项部分很靠前的一段就足以看到我要的那几项,而楼主的环境里需要打印更多内容才看得到。看看前面的记录的对应关系?
cheney_love 2014-05-18
RednaxelaFX 写道
那是因为楼主提供的日志显示,您的Class文件里您关心的那几个String常量位于常量池更靠后的位置(例如"a1"的index是16)而我的Class文件里它位于更前的位置(例如"a1"的index是2),所以我只需要打印constantPoolOopDesc里常量项部分很靠前的一段就足以看到我要的那几项,而楼主的环境里需要打印更多内容才看得到。看看前面的记录的对应关系?


谢谢大神指点:根据您的提示这次多打印了一些内容,总算是找到了这几个变量。
先简要的说说这几天学习中一点浅显的认识吧(基于JDK6):
程序里面 String 类型的常量应该是存放在StringTable 里面,所有的符号都存在SymbolTable 里面,StringTable 和 SymbolTable都继承了BasicHashtable ,所以他们的存储结构应该是个HashTable<pointer,value>的结构,而constant pool 里面只是存储的是String(symbol)在StringTable (symbolTable)中的指针。

打印StringTable:
VM vm = VM.getVM();
		StringTable st = vm.getStringTable();
		st.stringsDo(new StringTable.StringVisitor() {
			@Override
			public void visit(Instance paramInstance) {
				String name  = OopUtilities.stringOopToString(paramInstance);
				System.out.println(paramInstance+":"+name);
			}
		});


打印SymbolTable:
SymbolTable smt = vm.getSymbolTable();
		smt.symbolsDo(new SymbolTable.SymbolVisitor() {
			
			@Override
			public void visit(Symbol paramSymbol) {
				System.out.println(paramSymbol+":"+new String(paramSymbol.asByteArray()));
			}
		});


拿打印出得对象数据和在SA里使用命令得到的数据是一致的。
万里长征迈出总算是第一步了。
再次谢谢R大
Global site tag (gtag.js) - Google Analytics