JVM Object 的内存布局
对象的生命周期:
- load
- disk -> memory ClassLoader
- static initializers static fields
- 触发原因: new/访问静态成员/loader加载等
- loaded 加载完
- create
- allocate memory 分配内存
- constructor 构造, 注意是在
static
之后执行的. - created
- live
- in use 使用. Root Set 可以找到(且被使用)
- invisible 不可见, 泄漏. Root Set 可以找到, 但是没有使用.
- unreachable 不可达. 会被回收.
- destroy/gc
- collected
- finalize
- deallocated
Object 在内存中的格式(Object Memory Layout). 注意是 HotSpot
的!! 其它虚拟机差异不会很大, 都是基于 JVM 标准的。
- 对象头: Object Header。
- 实例数据: Instance Data。
- 对齐填充: 64bit HotSpot 8 字节对齐. 如果整体大小不是8的倍数, 通过
padding
补齐, 让对象在内存中比较整齐。
对象头
对象头的信息是与自身定义的数据是没有关系的额外存储成本, 所以 Mark Word 被设置为一个非固定的数据结构, 以便更有效地存储数据. 它会根据对象本身的状态, 复用自己的存储空间. 由三部分组成.
Mark Word格式
4 or 8 bytes。看系统位数。
- hashCode. 对象的 hashCode.(基于内存地址, 基于自增id)
- age. 分代年龄. 默认15次(也是最大值)
- 锁标志位, 3bit
- unlocked : 01
- biased 偏向锁 101
- light-weight locked : 00
- heavy-weight locked : 10
- marked for gc : 11
- Lock Record Address
- 轻量级锁(指向栈中的锁记录, 栈是线程独有的数据, 不是共享的, 线程检查如果不是指向自己就需要竞争锁)
- 检查
Mark Word
是否指向当前线程的栈
- Monitor Address. 指向对象的 Monitor
- Forwarding Address. gc自己使用. 比如说指向下一个对象
klass: 4 or 8 bytes. 指向Object的元数据(方法区), 长度看位数.
arraylength 是数组独有的. Oop: Object Operate.
32bit系统
|----------------------------------------------------------------------------------------|--------------------|
| Object Header (64 bits) | State |
|-------------------------------------------------------|--------------------------------|--------------------|
| Mark Word (32 bits) | Klass Word (32 bits) | |
|-------------------------------------------------------|--------------------------------|--------------------|
| identity_hashcode:25 | age:4 | biased_lock:1 | lock:2 | OOP to metadata object | Normal |
|-------------------------------------------------------|--------------------------------|--------------------|
| thread:23 | epoch:2 | age:4 | biased_lock:1 | lock:2 | OOP to metadata object | Biased |
|-------------------------------------------------------|--------------------------------|--------------------|
| ptr_to_lock_record:30 | lock:2 | OOP to metadata object | Lightweight Locked |
|-------------------------------------------------------|--------------------------------|--------------------|
| ptr_to_heavyweight_monitor:30 | lock:2 | OOP to metadata object | Heavyweight Locked |
|-------------------------------------------------------|--------------------------------|--------------------|
| | lock:2 | OOP to metadata object | Marked for GC |
|-------------------------------------------------------|--------------------------------|--------------------|
64bit系统
|------------------------------------------------------------------------------------------------------------|--------------------|
| Object Header (128 bits) | State |
|------------------------------------------------------------------------------|-----------------------------|--------------------|
| Mark Word (64 bits) | Klass Word (64 bits) | |
|------------------------------------------------------------------------------|-----------------------------|--------------------|
| unused:25 | identity_hashcode:31 | unused:1 | age:4 | biased_lock:1 | lock:2 | OOP to metadata object | Normal |
|------------------------------------------------------------------------------|-----------------------------|--------------------|
| thread:54 | epoch:2 | unused:1 | age:4 | biased_lock:1 | lock:2 | OOP to metadata object | Biased |
|------------------------------------------------------------------------------|-----------------------------|--------------------|
| ptr_to_lock_record:62 | lock:2 | OOP to metadata object | Lightweight Locked |
|------------------------------------------------------------------------------|-----------------------------|--------------------|
| ptr_to_heavyweight_monitor:62 | lock:2 | OOP to metadata object | Heavyweight Locked |
|------------------------------------------------------------------------------|-----------------------------|--------------------|
| | lock:2 | OOP to metadata object | Marked for GC |
|------------------------------------------------------------------------------|-----------------------------|--------------------|
注意描述. 总得来说.
- 有严格定义
- 不同虚拟机可能会不同
- 分成头部和实例数据, 可能还有Padding
空 Object 多大
64bit系统下,首先肯定是 8 的倍数,而Mark Word
最大占用 8byte,而Klass占用是8byte,对齐后就是16byte。
加上还有地址引用,32bit系统是4byte,64bit系统是8byte。
结论:16byte
(单纯对象头,堆中) + 8byte
(地址引用,栈中) = 24byte 是 Java
对象的最小值。