当前位置:   article > 正文

HotSpotVM 对象机制实现浅析#1

getjavamirror()

今天来看下,借助HotSpot SA这个工具,HotSpot VM所实现的对象机制。关于HotSpot SA前面已有几篇博文介绍过了,这里再说一点,SA提供的大多是HotSpot的镜像,所以非常有助于我们理解HotSpotVM,不管是运行时还是具体代码实现。

oop

那么HotSpot的对象机制应该从哪扯起呢?oop无疑。oop又是啥?

An “oop”, or “ordinary object pointer” in HotSpot parlance is a managed pointer to an object. It is normally the same size as a native machine pointer. A managed pointer is carefully tracked by the Java application and GC subsystem, so that storage for unused objects can be reclaimed.

也就是说,我们平时经常提及的对象实例,在HotSpot的内部表示,实际上是一个oop。具体地,oop的定义是oopDesc结构体,其中很重要的两个字段,

  1. volatile markOop _mark;
  2. union _metadata {
  3. wideKlassOop _klass;
  4. narrowOop _compressed_klass;
  5. } _metadata;

_mark是用于GC,对象锁的字段,而_metadata,很明显,就是这个实例的Class元数据。

oop有一个层次结构

  1. // OBJECT hierarchy
  2. // This hierarchy is a representation hierarchy, i.e. if A is a superclass
  3. // of B, A's representation is a prefix of B's representation.


  1. typedef class oopDesc* oop;
  2. typedef class instanceOopDesc* instanceOop;
  3. typedef class methodOopDesc* methodOop;
  4. typedef class constMethodOopDesc* constMethodOop;
  5. typedef class methodDataOopDesc* methodDataOop;
  6. typedef class arrayOopDesc* arrayOop;
  7. typedef class objArrayOopDesc* objArrayOop;
  8. typedef class typeArrayOopDesc* typeArrayOop;
  9. typedef class constantPoolOopDesc* constantPoolOop;
  10. typedef class constantPoolCacheOopDesc* constantPoolCacheOop;
  11. typedef class klassOopDesc* klassOop;
  12. typedef class markOopDesc* markOop;
  13. typedef class compiledICHolderOopDesc* compiledICHolderOop;


  1. // The klass hierarchy is separate from the oop hierarchy.
  2. class Klass;
  3. class instanceKlass;
  4. class instanceMirrorKlass;
  5. class instanceRefKlass;
  6. class methodKlass;
  7. class constMethodKlass;
  8. class methodDataKlass;
  9. class klassKlass;
  10. class instanceKlassKlass;
  11. class arrayKlassKlass;
  12. class objArrayKlassKlass;
  13. class typeArrayKlassKlass;
  14. class arrayKlass;
  15. class objArrayKlass;
  16. class typeArrayKlass;
  17. class constantPoolKlass;
  18. class constantPoolCacheKlass;
  19. class compiledICHolderKlass;

这些类在SA里面会有镜像,所以我们很容易就可以通过SA来看看这些oop,klass到底是个啥。但是这里有一点要注意,在HotSpot中,oop与klass体系,注释中也说到了,是分开的,然后采用组合的方式,所以会有klassOop,而在SA中,则是采用了继承的方式,klass直接继承了oop。是SA的开发者偷懒了吗:)

下面直接上代码看下如何使用SA来帮助我们理解oop体系,

  1. public class Main {
  2. public static void main(String[] args) throws Throwable {
  3. new Foo(8888);
  4. System.in.read();
  5. }
  6. }


  1. public class Foo {
  2. public static int foo_static_i = 7777777;
  3. private int foo_instance_i;
  4. public Foo(int foo_instance_i) {
  5. this.foo_instance_i = foo_instance_i;
  6. }
  7. public int getFoo_instance_i() {
  8. return foo_instance_i;
  9. }
  10. }


  1. import sun.jvm.hotspot.oops.*;
  2. import sun.jvm.hotspot.runtime.VM;
  3. import sun.jvm.hotspot.tools.Tool;
  4. public class KlassKicker extends Tool {
  5. public static void main(String[] args) throws Exception{
  6. KlassKicker kk = new KlassKicker();
  7. kk.start(args);
  8. kk.stop();
  9. }
  10. @Override
  11. public void run() {
  12. VM vm = VM.getVM();
  13. final ObjectHeap objectHeap = vm.getObjectHeap();
  14. objectHeap.iterate(new HeapVisitor() {
  15. @Override
  16. public void prologue(long l) {
  17. }
  18. @Override
  19. public boolean doObj(Oop oop) {
  20. System.out.println("");
  21. System.out.println("OOP#"+oop);
  22. oop.iterate(new OopPrinter(System.out), true);
  23. System.out.println("");
  24. System.out.println("OOP.KLASS#"+oop.getKlass());
  25. oop.getKlass().iterate(new OopPrinter(System.out), true);
  26. System.out.println("");
  27. System.out.println("OOP.KLASS.MIRROR#"+oop.getKlass().getJavaMirror());
  28. oop.getKlass().getJavaMirror().iterate(new OopPrinter(System.out), true);
  29. System.out.println("");
  30. System.out.println("OOP.KLASS.KLASS#" + oop.getKlass().getKlass());
  31. oop.getKlass().getKlass().iterate(new OopPrinter(System.out), true);
  32. System.out.println("");
  33. System.out.println("OOP.KLASS.KLASS.KLASS#" + oop.getKlass().getKlass().getKlass());
  34. oop.getKlass().getKlass().getKlass().iterate(new OopPrinter(System.out), true);
  35. System.out.println("");
  36. System.out.println("OOP.KLASS.KLASS.KLASS.KLASS#" + oop.getKlass().getKlass().getKlass().getKlass());
  37. oop.getKlass().getKlass().getKlass().getKlass().iterate(new OopPrinter(System.out), true);
  38. return false;
  39. }
  40. @Override
  41. public void epilogue() {
  42. }
  43. }, new ObjectHeap.ObjectFilter() {
  44. @Override
  45. public boolean canInclude(Oop oop) {
  46. Klass klass = oop.getKlass();
  47. return klass.getName() != null &&
  48. "me/kisimple/just4fun/Foo".equals(klass.getName().asString());
  49. }
  50. });
  51. }
  52. }

通过继承sun.jvm.hotspot.tools.Tool可以很方便地使用SA的API。栗子中我们直接遍历了虚拟机运行时的堆,并且通过Filter可以只处理我们new出来的Foo对象实例。

要运行SA Tool需要将目标进程pid传过去。输出结果如下,

  1. Attaching to process ID 5508, please wait...
  2. Debugger attached successfully.
  3. Server compiler detected.
  4. JVM version is 24.51-b03
  5. OOP#sun.jvm.hotspot.oops.Instance@d6157f10
  6. Oop for me/kisimple/just4fun/Foo @ 0x00000007d6157f10 (object size = 16)
  7. - _mark: {0} :1
  8. - _metadata._compressed_klass: {8} :InstanceKlass for me/kisimple/just4fun/Foo @ 0x000000077d0c3010
  9. - foo_instance_i: {12} :8888
  10. OOP.KLASS#sun.jvm.hotspot.oops.InstanceKlass@7d0c3010
  11. InstanceKlass for me/kisimple/just4fun/Foo @ 0x000000077d0c3010 (object size = 560)
  12. - _mark: {0} :1
  13. - _metadata._compressed_klass: {8} :InstanceKlassKlass @ 0x000000077ce00270
  14. - _java_mirror: {120} :Oop for java/lang/Class @ 0x00000007d6157e98
  15. - _super: {128} :InstanceKlass for java/lang/Object @ 0x000000077ce02bb0
  16. - _layout_helper: {24} :16
  17. - _access_flags: {156} :2097185
  18. - _subklass: {136} :null
  19. - _next_sibling: {144} :InstanceKlass for java/lang/reflect/TypeVariable @ 0x000000077d0c0fa8
  20. - _alloc_count: {160} :0
  21. - _array_klasses: {200} :null
  22. - _methods: {208} :ObjArray @ 0x000000077d0c2d38
  23. - _method_ordering: {216} :[I @ 0x000000077d0c2ff0
  24. - _local_interfaces: {224} :ObjArray @ 0x000000077ce01bf8
  25. - _transitive_interfaces: {232} :ObjArray @ 0x000000077ce01bf8
  26. - _fields: {240} :[S @ 0x000000077d0c2d10
  27. - _constants: {248} :ConstantPool for me/kisimple/just4fun/Foo @ 0x000000077d0c2bc0
  28. - _class_loader: {256} :Oop for sun/misc/Launcher$AppClassLoader @ 0x00000007d60a32f0
  29. - _protection_domain: {264} :Oop for java/security/ProtectionDomain @ 0x00000007d6152fa8
  30. - _signers: {272} :null
  31. - _inner_classes: {280} :[S @ 0x000000077ce01bd8
  32. - _nonstatic_field_size: {360} :1
  33. - _static_field_size: {364} :1
  34. - _static_oop_field_count: {368} :0
  35. - _nonstatic_oop_map_size: {372} :0
  36. - _is_marked_dependent: {376} :0
  37. - _init_state: {490} :5
  38. - _vtable_len: {392} :6
  39. - _itable_len: {396} :2
  40. OOP.KLASS.MIRROR#sun.jvm.hotspot.oops.Instance@d6157e98
  41. Oop for java/lang/Class @ 0x00000007d6157e98 (object size = 120)
  42. - _mark: {0} :501373421313
  43. - _metadata._compressed_klass: {8} :InstanceKlass for java/lang/Class @ 0x000000077ce15e48
  44. - cachedConstructor: {12} :null
  45. - newInstanceCallerCache: {16} :null
  46. - name: {20} :null
  47. - declaredFields: {24} :null
  48. - publicFields: {28} :null
  49. - declaredMethods: {32} :null
  50. - publicMethods: {36} :null
  51. - declaredConstructors: {40} :null
  52. - publicConstructors: {44} :null
  53. - declaredPublicFields: {48} :null
  54. - declaredPublicMethods: {52} :null
  55. - classRedefinedCount: {96} :0
  56. - lastRedefinedCount: {100} :0
  57. - genericInfo: {56} :null
  58. - enumConstants: {60} :null
  59. - enumConstantDirectory: {64} :null
  60. - annotations: {68} :null
  61. - declaredAnnotations: {72} :null
  62. - annotationType: {76} :null
  63. - classValueMap: {80} :null
  64. Oop for java/lang/Class @ 0x00000007d6157e98 (object size = 120)
  65. - foo_static_i: {112} :7777777
  66. OOP.KLASS.KLASS#sun.jvm.hotspot.oops.InstanceKlassKlass@7ce00270
  67. InstanceKlassKlass @ 0x000000077ce00270 (object size = 208)
  68. - _mark: {0} :1
  69. - _metadata._compressed_klass: {8} :KlassKlass @ 0x000000077ce00000
  70. - _java_mirror: {120} :null
  71. - _super: {128} :null
  72. - _layout_helper: {24} :0
  73. - _access_flags: {156} :0
  74. - _subklass: {136} :null
  75. - _next_sibling: {144} :null
  76. - _alloc_count: {160} :0
  77. OOP.KLASS.KLASS.KLASS#sun.jvm.hotspot.oops.KlassKlass@7ce00000
  78. KlassKlass @ 0x000000077ce00000 (object size = 208)
  79. - _mark: {0} :1
  80. - _metadata._compressed_klass: {8} :KlassKlass @ 0x000000077ce00000
  81. - _java_mirror: {120} :null
  82. - _super: {128} :null
  83. - _layout_helper: {24} :0
  84. - _access_flags: {156} :0
  85. - _subklass: {136} :null
  86. - _next_sibling: {144} :null
  87. - _alloc_count: {160} :0
  88. OOP.KLASS.KLASS.KLASS.KLASS#sun.jvm.hotspot.oops.KlassKlass@7ce00000
  89. KlassKlass @ 0x000000077ce00000 (object size = 208)
  90. - _mark: {0} :1
  91. - _metadata._compressed_klass: {8} :KlassKlass @ 0x000000077ce00000
  92. - _java_mirror: {120} :null
  93. - _super: {128} :null
  94. - _layout_helper: {24} :0
  95. - _access_flags: {156} :0
  96. - _subklass: {136} :null
  97. - _next_sibling: {144} :null
  98. - _alloc_count: {160} :0

下面就来说说这些输出结果。

instanceOop

从上面的结果可以看到,对象实例,具体一点,是一个instanceOop,它的layout也很清晰,

  1. +-----------+
  2. | _mark |
  3. +-----------+
  4. | _metadata |
  5. +-----------+
  6. | instance |
  7. | fields |
  8. +-----------+

instanceKlass

instanceOop的metadata是一个instanceKlass,也就是用来描述类的数据结构,它的layout是这样的,

  1. // An instanceKlass is the VM level representation of a Java class.
  2. // It contains all information needed for a class at execution runtime.
  3. // instanceKlass layout:
  4. // [header ] klassOop
  5. // [klass pointer ] klassOop
  6. // [C++ vtbl pointer ] Klass
  7. // [subtype cache ] Klass
  8. // [instance size ] Klass
  9. // [java mirror ] Klass
  10. // [super ] Klass
  11. // [access_flags ] Klass
  12. // [name ] Klass
  13. // [first subklass ] Klass
  14. // [next sibling ] Klass
  15. // [array klasses ]
  16. // [methods ]
  17. // [local interfaces ]
  18. // [transitive interfaces ]
  19. // [fields ]
  20. // [constants ]
  21. // [class loader ]
  22. // [protection domain ]
  23. // [signers ]
  24. // [source file name ]
  25. // [inner classes ]
  26. // [static field size ]
  27. // [nonstatic field size ]
  28. // [static oop fields size ]
  29. // [nonstatic oop maps size ]
  30. // [has finalize method ]
  31. // [deoptimization mark bit ]
  32. // [initialization state ]
  33. // [initializing thread ]
  34. // [Java vtable length ]
  35. // [oop map cache (stack maps) ]
  36. // [EMBEDDED Java vtable ] size in words = vtable_len
  37. // [EMBEDDED nonstatic oop-map blocks] size in words = nonstatic_oop_map_size
  38. // The embedded nonstatic oop-map blocks are short pairs (offset, length)
  39. // indicating where oops are located in instances of this klass.
  40. // [EMBEDDED implementor of the interface] only exist for interface
  41. // [EMBEDDED host klass ] only exist for an anonymous class (JSR 292 enabled)

在我们的输出结果中,可以看到methods这个字段的值,_methods: {208} :ObjArray @ 0x000000077d0c2d38,这个ObjArray也是个oop,是数组对象,它的地址是0x000000077d0c2d38。下面我们使用SA自带的一个小神器,HSDB(HotSpotDeBugger),来看看这个地址上面是个啥。

很简单,直接java sun.jvm.hotspot.HSDB启动HSDB。启动之后需要先attach到目标进程,然后既可以使用图形界面(Tools->inspect),也可以使用命令行(Windows->console,这其实是命令行版本的HSDB,也就是sun.jvm.hotspot.CLHSDB)来inspect这些地址(还有其他很多功能,可以自己把玩一下),结果如下,

可以看到,是一个methodOop的数组对象。

Java镜像

接下来输出的实际是instanceKlass_java_mirror字段,也是个oop。那么这个_java_mirror又是个啥?看下这篇官网文档中的描述,

The instanceKlass refers to a java mirror, which is the instance of java.lang.Class mirroring this class.

看下面的栗子会更容易理解这个镜像,

  1. public static void main(String[] args) throws Throwable {
  2. System.out.println(Main.class);
  3. System.out.println(Main.class.getClass());
  4. System.out.println(Main.class instanceof Class);
  5. }


  1. class me.kisimple.just4fun.Main
  2. class java.lang.Class
  3. true

这里的Main.class实际上就是上面所说的Java镜像,它是一个java.lang.Class的实例,因此Main.class instanceof Class才会是true。可以看到HotSpot将那些类变量(上面的foo_static_i)都放到这个镜像上面了。至于输出的很多字段都是null,感觉应该是SA有问题,暂不深究。

klassKlass

从后面的输出可以看出来,oop的klass链是下图这样的,

那么instanceKlassKlassklassKlass这俩货又是干啥用的?

引用R大的一段说明

HotSpot VM在JDK8之前的版本都是把Java对象和元数据对象以统一的方式由GC管理的。为了让GC能统一的处理这些对象,每个由GC管理的对象都继承自oopDesc,而每个oopDesc都有一个_klass字段指向描述它的Klass对象。GC在找到一个对象之后,要知道对象大小、对象里什么位置有GC需要知道的指针之类的信息,就会通过从_klass字段找到Klass对象,从Klass对象获取。更准确说Klass对象是嵌在klassOopDesc对象,以便Klass对象也同样得到GC的统一管理。

所以其实是由于将instanceKlass这样的元数据也使用oop由GC来管理才会引入了instanceKlassKlass到JDK8已经没有xxxKlassKlass,因为instanceKlass这些元数据已经被移出GC堆,也不再需要klassOopDesc来指向instanceKlass了,oopDesc_metadata字段定义已经改成下面这样了,

  1. union _metadata {
  2. /// 之前都是oop,现在直接指向Klass了
  3. Klass* _klass;
  4. narrowKlass _compressed_klass;
  5. } _metadata;

这应该也是移除PermGen的好处之一吧:)

这里有一个问题需要考虑下,为什么要多出xxxKlassKlass这一层呢?直接使用klassKlass来描述instanceKlass不OK吗(python就是这样的设计,见下文)?很明显,因为各种xxxKlassKlass要描述的xxxKlass并不同(xxxKlass的创建也都是由xxxKlassKlass来完成,例如instanceKlassKlass::allocate_instance_klass),具体的看代码吧:)

还有一点说明,instanceKlassKlass是个单例

  1. // An InstanceKlassKlass is the klass of an InstanceKlass.
  2. // There only exist one instance Universe::instanceKlassKlassObj()

在虚拟机启动的时候,会调用instanceKlassKlass::create_klass来创建这个universe::instanceKlassKlassObj

当然,klassKlass也会是单例。

数组对象

下面依葫芦画瓢,看下数组对象在HotSpotVM中是怎么表示的。new了这么一个数组对象,Foo[] fooArray = new Foo[]{new Foo(1234), new Foo(5678)},修改下Filter,

  1. @Override
  2. public boolean canInclude(Oop oop) {
  3. if(oop.isObjArray()) {
  4. Klass klass = ((ObjArrayKlass)oop.getKlass()).getElementKlass();
  5. return klass.getName() != null &&
  6. "me/kisimple/just4fun/Foo".equals(klass.getName().asString());
  7. }
  8. return false;
  9. }

输出如下,
  1. OOP#sun.jvm.hotspot.oops.ObjArray@d6157fc8
  2. ObjArray @ 0x00000007d6157fc8 (object size = 24)
  3. - _mark: {0} :1
  4. - _metadata._compressed_klass: {8} :ObjArrayKlass for InstanceKlass for me/kisimple/just4fun/Foo @ 0x000000077d0c3278
  5. - 0: {16} :Oop for me/kisimple/just4fun/Foo @ 0x00000007d6157fe0
  6. - 1: {20} :Oop for me/kisimple/just4fun/Foo @ 0x00000007d6157ff0
  7. OOP.KLASS#sun.jvm.hotspot.oops.ObjArrayKlass@7d0c3278
  8. ObjArrayKlass for InstanceKlass for me/kisimple/just4fun/Foo @ 0x000000077d0c3278 (object size = 536)
  9. - _mark: {0} :1
  10. - _metadata._compressed_klass: {8} :ObjArrayKlassKlass @ 0x000000077ce001a0
  11. - _java_mirror: {120} :Oop for java/lang/Class @ 0x00000007d6157f58
  12. - _super: {128} :ObjArrayKlass for InstanceKlass for java/lang/Object @ 0x000000077cea4810
  13. - _layout_helper: {24} :-2146431998
  14. - _access_flags: {156} :-2147483648
  15. - _subklass: {136} :null
  16. - _next_sibling: {144} :null
  17. - _alloc_count: {160} :0
  18. - _dimension: {200} :1
  19. - _higher_dimension: {208} :null
  20. - _lower_dimension: {216} :null
  21. - _vtable_len: {224} :5
  22. - _alloc_size: {228} :0
  23. - _component_mirror: {232} :Oop for java/lang/Class @ 0x00000007d6157ee0
  24. - _element_klass: {240} :InstanceKlass for me/kisimple/just4fun/Foo @ 0x000000077d0c3048
  25. - _bottom_klass: {248} :InstanceKlass for me/kisimple/just4fun/Foo @ 0x000000077d0c3048
  26. OOP.KLASS.KLASS#sun.jvm.hotspot.oops.ObjArrayKlassKlass@7ce001a0
  27. ObjArrayKlassKlass @ 0x000000077ce001a0 (object size = 208)
  28. - _mark: {0} :1
  29. - _metadata._compressed_klass: {8} :KlassKlass @ 0x000000077ce00000
  30. - _java_mirror: {120} :null
  31. - _super: {128} :null
  32. - _layout_helper: {24} :0
  33. - _access_flags: {156} :0
  34. - _subklass: {136} :null
  35. - _next_sibling: {144} :null
  36. - _alloc_count: {160} :0
  37. OOP.KLASS.KLASS.KLASS#sun.jvm.hotspot.oops.KlassKlass@7ce00000
  38. KlassKlass @ 0x000000077ce00000 (object size = 208)
  39. - _mark: {0} :1
  40. - _metadata._compressed_klass: {8} :KlassKlass @ 0x000000077ce00000
  41. - _java_mirror: {120} :null
  42. - _super: {128} :null
  43. - _layout_helper: {24} :0
  44. - _access_flags: {156} :0
  45. - _subklass: {136} :null
  46. - _next_sibling: {144} :null
  47. - _alloc_count: {160} :0

上面的输出有个问题,本来 arrayOop 的layout应该是这样的,
  1. // The layout of array Oops is:
  2. //
  3. // markOop
  4. // klassOop // 32 bits if compressed but declared 64 in LP64.
  5. // length // shares klass memory or allocated after declared fields.

但是输出中并没有看到 _length 字段,不知道是SA的问题,还是下面这个原因?
  1. // The _length field is not declared in C++. It is allocated after the
  2. // declared nonstatic fields in arrayOopDesc if not compressed, otherwise
  3. // it occupies the second half of the _klass field in oopDesc.

vs. python

python(准确点说是CPython)的对象机制实现其实跟HotSpotVM类似,下面将HotSpot的实现对应到python中来(使用python2.7版本)。

python中用于实现对象的基础数据结构定义在object.h中。HotSpot的instanceOop对应了PyObjectarrayOop对应了PyVarObject

  1. #ifdef Py_TRACE_REFS
  2. /* Define pointers to support a doubly-linked list of all live heap objects. */
  3. #define _PyObject_HEAD_EXTRA \
  4. struct _object *_ob_next; \
  5. struct _object *_ob_prev;
  6. #define _PyObject_EXTRA_INIT 0, 0,
  7. #else
  8. #define _PyObject_HEAD_EXTRA
  9. #define _PyObject_EXTRA_INIT
  10. #endif
  11. /* PyObject_HEAD defines the initial segment of every PyObject. */
  12. #define PyObject_HEAD \
  13. _PyObject_HEAD_EXTRA \
  14. Py_ssize_t ob_refcnt; \
  15. struct _typeobject *ob_type;
  16. #define PyObject_HEAD_INIT(type) \
  17. _PyObject_EXTRA_INIT \
  18. 1, type,
  19. #define PyVarObject_HEAD_INIT(type, size) \
  20. PyObject_HEAD_INIT(type) size,
  21. /* PyObject_VAR_HEAD defines the initial segment of all variable-size
  22. * container objects. These end with a declaration of an array with 1
  23. * element, but enough space is malloc'ed so that the array actually
  24. * has room for ob_size elements. Note that ob_size is an element count,
  25. * not necessarily a byte count.
  26. */
  27. #define PyObject_VAR_HEAD \
  28. PyObject_HEAD \
  29. Py_ssize_t ob_size; /* Number of items in variable part */
  30. #define Py_INVALID_SIZE (Py_ssize_t)-1
  31. /* Nothing is actually declared to be a PyObject, but every pointer to
  32. * a Python object can be cast to a PyObject*. This is inheritance built
  33. * by hand. Similarly every pointer to a variable-size Python object can,
  34. * in addition, be cast to PyVarObject*.
  35. */
  36. typedef struct _object {
  37. PyObject_HEAD
  38. } PyObject;
  39. typedef struct {
  40. PyObject_VAR_HEAD
  41. } PyVarObject;

两者的头部信息中,只有一个ob_refcnt来实现引用计数,不像HotSpot用了一个比较重的_mark对象指针(所以python没有办法像Java那样使用对象锁)。

Klass则对应了PyTypeObject

  1. typedef struct _typeobject {
  2. PyObject_VAR_HEAD
  3. const char *tp_name; /* For printing, in format "<module>.<name>" */
  4. Py_ssize_t tp_basicsize, tp_itemsize; /* For allocation */
  5. /* Methods to implement standard operations */
  6. destructor tp_dealloc;
  7. printfunc tp_print;
  8. getattrfunc tp_getattr;
  9. setattrfunc tp_setattr;
  10. cmpfunc tp_compare;
  11. reprfunc tp_repr;
  12. /* Method suites for standard classes */
  13. PyNumberMethods *tp_as_number;
  14. PySequenceMethods *tp_as_sequence;
  15. PyMappingMethods *tp_as_mapping;
  16. /* More standard operations (here for binary compatibility) */
  17. hashfunc tp_hash;
  18. ternaryfunc tp_call;
  19. reprfunc tp_str;
  20. getattrofunc tp_getattro;
  21. setattrofunc tp_setattro;
  22. /* Functions to access object as input/output buffer */
  23. PyBufferProcs *tp_as_buffer;
  24. /* Flags to define presence of optional/expanded features */
  25. long tp_flags;
  26. const char *tp_doc; /* Documentation string */
  27. /* Assigned meaning in release 2.0 */
  28. /* call function for all accessible objects */
  29. traverseproc tp_traverse;
  30. /* delete references to contained objects */
  31. inquiry tp_clear;
  32. /* Assigned meaning in release 2.1 */
  33. /* rich comparisons */
  34. richcmpfunc tp_richcompare;
  35. /* weak reference enabler */
  36. Py_ssize_t tp_weaklistoffset;
  37. /* Added in release 2.2 */
  38. /* Iterators */
  39. getiterfunc tp_iter;
  40. iternextfunc tp_iternext;
  41. /* Attribute descriptor and subclassing stuff */
  42. struct PyMethodDef *tp_methods;
  43. struct PyMemberDef *tp_members;
  44. struct PyGetSetDef *tp_getset;
  45. struct _typeobject *tp_base;
  46. PyObject *tp_dict;
  47. descrgetfunc tp_descr_get;
  48. descrsetfunc tp_descr_set;
  49. Py_ssize_t tp_dictoffset;
  50. initproc tp_init;
  51. allocfunc tp_alloc;
  52. newfunc tp_new;
  53. freefunc tp_free; /* Low-level free-memory routine */
  54. inquiry tp_is_gc; /* For PyObject_IS_GC */
  55. PyObject *tp_bases;
  56. PyObject *tp_mro; /* method resolution order */
  57. PyObject *tp_cache;
  58. PyObject *tp_subclasses;
  59. PyObject *tp_weaklist;
  60. destructor tp_del;
  61. /* Type attribute cache version tag. Added in version 2.6 */
  62. unsigned int tp_version_tag;
  63. #ifdef COUNT_ALLOCS
  64. /* these must be last and never explicitly initialized */
  65. Py_ssize_t tp_allocs;
  66. Py_ssize_t tp_frees;
  67. Py_ssize_t tp_maxalloc;
  68. struct _typeobject *tp_prev;
  69. struct _typeobject *tp_next;
  70. #endif
  71. } PyTypeObject;

上面的tp_methods应该就相当于是我们看到的instanceKlassmethods字段了。

还有那俩胃疼的instanceKlassKlassklassKlass对应的是啥?python的对象机制没有这么复杂,和这俩货对应的只有一个,PyType_Type,而它并不是又一个struct,它是一个PyTypeObject,在typeobject.c中定义,

  1. PyTypeObject PyType_Type = {
  2. PyVarObject_HEAD_INIT(&PyType_Type, 0)
  3. "type", /* tp_name */
  4. sizeof(PyHeapTypeObject), /* tp_basicsize */
  5. sizeof(PyMemberDef), /* tp_itemsize */
  6. (destructor)type_dealloc, /* tp_dealloc */
  7. 0, /* tp_print */
  8. 0, /* tp_getattr */
  9. 0, /* tp_setattr */
  10. 0, /* tp_compare */
  11. (reprfunc)type_repr, /* tp_repr */
  12. 0, /* tp_as_number */
  13. 0, /* tp_as_sequence */
  14. 0, /* tp_as_mapping */
  15. (hashfunc)_Py_HashPointer, /* tp_hash */
  16. (ternaryfunc)type_call, /* tp_call */
  17. 0, /* tp_str */
  18. (getattrofunc)type_getattro, /* tp_getattro */
  19. (setattrofunc)type_setattro, /* tp_setattro */
  20. 0, /* tp_as_buffer */
  21. Py_TPFLAGS_DEFAULT | Py_TPFLAGS_HAVE_GC |
  22. Py_TPFLAGS_BASETYPE | Py_TPFLAGS_TYPE_SUBCLASS, /* tp_flags */
  23. type_doc, /* tp_doc */
  24. (traverseproc)type_traverse, /* tp_traverse */
  25. (inquiry)type_clear, /* tp_clear */
  26. type_richcompare, /* tp_richcompare */
  27. offsetof(PyTypeObject, tp_weaklist), /* tp_weaklistoffset */
  28. 0, /* tp_iter */
  29. 0, /* tp_iternext */
  30. type_methods, /* tp_methods */
  31. type_members, /* tp_members */
  32. type_getsets, /* tp_getset */
  33. 0, /* tp_base */
  34. 0, /* tp_dict */
  35. 0, /* tp_descr_get */
  36. 0, /* tp_descr_set */
  37. offsetof(PyTypeObject, tp_dict), /* tp_dictoffset */
  38. type_init, /* tp_init */
  39. 0, /* tp_alloc */
  40. type_new, /* tp_new */
  41. PyObject_GC_Del, /* tp_free */
  42. (inquiry)type_is_gc, /* tp_is_gc */
  43. };

看上去要比HotSpot的实现清晰简洁一点。

下面我们再来对比下二者具体的整数对象的实现。python的整数对象定义在intobject.hpython3中已经统一到PyLongObject了),

  1. typedef struct {
  2. PyObject_HEAD
  3. long ob_ival;
  4. } PyIntObject;

而描述它的 PyTypeObject 则是 PyInt_Type
  1. PyTypeObject PyInt_Type = {
  2. PyVarObject_HEAD_INIT(&PyType_Type, 0)
  3. "int",
  4. ...
  5. };

然后我们再来看下HotSpot的整数对象,还是使用上面SA的栗子, Integer integer = new Integer(7777777) ,输出如下,
  1. OOP#sun.jvm.hotspot.oops.Instance@d6158058
  2. Oop for java/lang/Integer @ 0x00000007d6158058 (object size = 16)
  3. - _mark: {0} :1
  4. - _metadata._compressed_klass: {8} :InstanceKlass for java/lang/Integer @ 0x000000077cea0e78
  5. - value: {12} :7777777
  6. OOP.KLASS#sun.jvm.hotspot.oops.InstanceKlass@7cea0e78
  7. InstanceKlass for java/lang/Integer @ 0x000000077cea0e78 (object size = 624)
  8. - _mark: {0} :1
  9. - _metadata._compressed_klass: {8} :InstanceKlassKlass @ 0x000000077ce00270
  10. - _java_mirror: {120} :Oop for java/lang/Class @ 0x00000007d6003200
  11. - _super: {128} :InstanceKlass for java/lang/Number @ 0x000000077ce97230
  12. - _layout_helper: {24} :16
  13. - _access_flags: {156} :49
  14. - _subklass: {136} :null
  15. - _next_sibling: {144} :InstanceKlass for java/lang/Short @ 0x000000077ce9d238
  16. - _alloc_count: {160} :0
  17. - _array_klasses: {200} :ObjArrayKlass for InstanceKlass for java/lang/Integer @ 0x000000077d0bc920
  18. - _methods: {208} :ObjArray @ 0x000000077ce9dee0
  19. - _method_ordering: {216} :[I @ 0x000000077cea0dc0
  20. - _local_interfaces: {224} :ObjArray @ 0x000000077ce9de30
  21. - _transitive_interfaces: {232} :ObjArray @ 0x000000077cea0da8
  22. - _fields: {240} :[S @ 0x000000077ce9de48
  23. - _constants: {248} :ConstantPool for java/lang/Integer @ 0x000000077ce9d4a8
  24. - _class_loader: {256} :null
  25. - _protection_domain: {264} :null
  26. - _signers: {272} :null
  27. - _inner_classes: {280} :[S @ 0x000000077cea0d88
  28. - _nonstatic_field_size: {360} :1
  29. - _static_field_size: {364} :6
  30. - _static_oop_field_count: {368} :5
  31. - _nonstatic_oop_map_size: {372} :0
  32. - _is_marked_dependent: {376} :0
  33. - _init_state: {490} :5
  34. - _vtable_len: {392} :11
  35. - _itable_len: {396} :5

所以其实PyIntObject对应的还是一个instanceOop(oop使用offset的方式来填充实例数据,所以不需要重新再定义一个数据结构),而PyInt_Type应该说对应的是一个instanceKlass的实例,其实也可以说是java.lang.Integer了:)

参考资料

声明:本文内容由网友自发贡献,不代表【wpsshop博客】立场,版权归原作者所有,本站不承担相应法律责任。如您发现有侵权的内容,请联系我们。转载请注明出处:https://www.wpsshop.cn/w/笔触狂放9/article/detail/456545
推荐阅读
相关标签
  

闽ICP备14008679号