JVM

Java对象模型

Posted by Haiden on May 13, 2019

Java对象模型OOP-Klass

一个Java类在JVM中使用OOP-Klass模型用来描述class的属性和行为。

OOP(Ordinary Object Pointer)是普通对象指针, 把对象模型拆分为OOP和Klass两部分是因为不希望每个对象都有一个C ++ vtbl指针, 因此普通的oops没有任何虚拟功能。 他们将所有“虚拟”函数转发到它们的klass,klass具有vtbl并根据对象的实际类型执行C ++调度。

1 OOP

1.1 oopDesc结构

oopDesc是对象类的最高基类,oopDesc是抽象的。位于oop.cpp文件中。

1
2
3
4
5
6
7
8
9
class oopDesc {
  friend class VMStructs;
 private:
  volatile markOop  _mark; //对象头
  //元数据
  union _metadata {
    Klass*      _klass;   // 对应的Klass对象 
    narrowKlass _compressed_klass;
  } _metadata;

oopDesc主要包含两部分

  • _mark :是一个markOop实例,它描述了一个对象的头信息,用于存储对象的运行时记录信息,如哈希值、GC分代年龄、锁状态标志、线程持有的锁、偏向线程ID、偏向时间戳等:
  • _metadata :包含一个普通_klass和一个压缩后的_compressed_klass
1.2 markOop类结构

描述了一个对象的头信息,如哈希码、GC分代年龄、锁状态标志、线程持有的锁、偏向线程ID、偏向时间戳等等。

hash: 保存对象的哈希码 age: 保存对象的分代年龄 biased_lock: 偏向锁标识位 lock: 锁状态标识位 JavaThread*: 保存持有偏向锁的线程ID epoch: 保存偏向时间戳

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
//  32 bits: 32位虚拟机
//  --------
//   hash:25 ------------>| age:4    biased_lock:1 lock:2 (normal object)
//   JavaThread*:23 epoch:2 age:4    biased_lock:1 lock:2 (biased object)
//   size:32 ------------------------------------------>| (CMS free block)
//   PromotedObject*:29 ---------->| promo_bits:3 ----->| (CMS promoted object)
//
//  64 bits: 64位虚拟机
//  --------
//  unused:25 hash:31 -->| unused:1   age:4    biased_lock:1 lock:2 (normal object)
//  JavaThread*:54 epoch:2 unused:1   age:4    biased_lock:1 lock:2 (biased object)
//  PromotedObject*:61 --------------------->| promo_bits:3 ----->| (CMS promoted object)
//  size:64 ----------------------------------------------------->| (CMS free block)
//
//  unused:25 hash:31 -->| cms_free:1 age:4    biased_lock:1 lock:2 (COOPs && normal object)
//  JavaThread*:54 epoch:2 cms_free:1 age:4    biased_lock:1 lock:2 (COOPs && biased object)
//  narrowOop:32 unused:24 cms_free:1 unused:4 promo_bits:3 ----->| (COOPs && CMS promoted object)
//  unused:21 size:35 -->| cms_free:1 unused:7 ------------------>| (COOPs && CMS free block)

对象锁状态

markOop中不同的锁标识位,代表着不同的锁状态:

1
2
3
4
5
6
7
//  - the two lock bits are used to describe three states: locked/unlocked and monitor.
//
//    [ptr             | 00]  locked             ptr points to real header on stack
//    [header      | 0 | 01]  unlocked           regular object header
//    [ptr             | 10]  monitor            inflated lock (header is wapped out)
//    [ptr             | 11]  marked             used by markSweep to mark an object
//                                               not valid at any other time

对象头信息根据对象的状态复用自己的存储空间,不同锁状态下,对象存储空间存储的内容有所不同。

锁状态 存储内容 锁标志位 偏向锁标志位
无锁 哈希码、分代年龄 0 01
偏向锁 线程ID、时间戳、对象分代年龄 1 01
轻量级锁 指向栈中锁记录的指针ptr 00
重量级锁 指向monitor的指针ptr 10
GC标记 11

32位虚拟机中,无锁状态对象的存储内容如下

锁状态 25 bit 4 bit 1 bit 2 bit
无锁 对象hashcode 对象分代年龄 0 01

32位虚拟机中,有锁状态对象的存储内容如下

1.3 oop类层级

oop类层级结构在src/hotspot/share/oops/oopsHierarchy.hpp文件中, oop体系如下

1
2
3
4
5
typedef class oopDesc*                            oop;
typedef class   instanceOopDesc*            instanceOop;
typedef class   arrayOopDesc*                    arrayOop;
typedef class     objArrayOopDesc*            objArrayOop;
typedef class     typeArrayOopDesc*            typeArrayOop;

2 Klass

2.1 Klass类层级

Klass类层级结构在src/hotspot/share/oops/oopsHierarchy.hpp文件中, Klass体系如下

1
2
3
4
5
6
7
8
class Klass;
class   InstanceKlass;
class     InstanceMirrorKlass;
class     InstanceClassLoaderKlass;
class     InstanceRefKlass;
class   ArrayKlass;
class     ObjArrayKlass;
class     TypeArrayKlass;

Klass对象作用:

  • 语言级别的类对象(方法字典等)
  • 为对象提供虚拟机调度行为