[讨论] 怎么查看运行时常量池的数据?
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大 ![]() |