注意:环境为jdk8
1.对象内存布局
在HotSpot虚拟机里,对象在堆内存中的存储布局可以划分为三个部分:对象头(Header),实例 数据(Instance Data)和对齐填充(Padding)。
HotSpot虚拟机对象的对象头部分包括两类信息。
第一类是用于存储对象自身的运行时数据,如哈 希码(HashCode)、GC分代年龄、锁状态标志、线程持有的锁、偏向线程ID、偏向时间戳等,这部 分数据的长度在32位和64位的虚拟机(未开启压缩指针)中分别为32个比特和64个比特,官方称它 为“Mark Word”。对象需要存储的运行时数据很多,其实已经超出了32、64位Bitmap结构所能记录的 最大限度,但对象头里的信息是与对象自身定义的数据无关的额外存储成本,考虑到虚拟机的空间效 率,Mark Word被设计成一个有着动态定义的数据结构,以便在极小的空间内存储尽量多的数据,根 据对象的状态复用自己的存储空间。例如在32位的HotSpot虚拟机中,如对象未被同步锁锁定的状态 下,Mark Word的32个比特存储空间中的25个比特用于存储对象哈希码,4个比特用于存储对象分代年 龄,2个比特用于存储锁标志位,1个比特固定为0,在其他状态(轻量级锁定、重量级锁定、GC标 记、可偏向)下对象的存储内容。
对象头的另外一部分是类型指针,即对象指向它的类型元数据的指针,Java虚拟机通过这个指针 来确定该对象是哪个类的实例。并不是所有的虚拟机实现都必须在对象数据上保留类型指针,换句话说,查找对象的元数据信息并不一定要经过对象本身。此外,如果对 象是一个Java数组,那在对象头中还必须有一块用于记录数组长度的数据,因为虚拟机可以通过普通 Java对象的元数据信息确定Java对象的大小,但是如果数组的长度是不确定的,将无法通过元数据中的信息推断出数组的大小。
2.Shallow Heap(浅堆)
2.1解释
- Shallow Heap是指对象本身占用的内存大小。它只考虑对象的直接内存消耗,不包括该对象引用的其他对象。
- 例如,一个简单的Java对象包含一些基本类型的字段和对象引用,那么Shallow Heap就是这些字段的大小总和。
2.2占用字节说明
一个对象引用会占据4个字节,一个int类型会占据4个字节,long型变量会占据8个字节,每个对象头需要占用16个字节(不开启指针压缩)
2.3样例
B
的 Shallow Heap
- address (String 引用): 4字节
- longitude (BigDecimal 引用): 4字节
- latitude (BigDecimal 引用): 4字节
- 对象头: 16字节
因此,
B
的 Shallow Heap 大小为:Shallow Heap of B=16+4+4+4=28字节
String的Shallow Heap
String
对象由以下部分组成:
- 对象头: 16字节
- int hash: 4字节
- int offset: 4字节
- int count: 4字节
- char[] 引用: 4字节
因此,
String
对象的 Shallow Heap 大小为:Shallow Heap of String=16+4+4+4+4=32字节
此外,
String
还引用了一个char[]
数组。假设字符串“张三”和“北京”的长度分别为2和2,则char[]
数组的 Shallow Heap 大小为:
- char[] 数组对象头: 16字节
- char[] 数组数据: 2 * 2字节 = 4字节
总的 Shallow Heap 大小为:
Shallow Heap of char[]=16+4=20字节
BigDecimal的Shallow Heap
BigDecimal
对象包含以下字段:
- int scale: 4字节
- int precision: 4字节
- int bitCount: 4字节
- int compact: 8字节(使用 long 存储)
- BigInteger intVal 引用: 4字节
- 对象头: 16字节
因此,
BigDecimal
对象的 Shallow Heap 大小为:Shallow Heap of BigDecimal=16+4+4+4+8+4=40字节
BigDecimal
对象通常还包含一个BigInteger
对象,假设其包含一个int[]
数组引用。BigInteger
对象的 Shallow Heap 大小为:
- 对象头: 16字节
- int[] 引用: 4字节
- signum: 4字节
假设
BigInteger
的int[]
数组包含2个元素(每个int
4字节),则 Shallow Heap 为:Shallow Heap of BigInteger=16+4+4+(16+2∗4)=48字节
3.Retained Set(保留集)
3.1解释
- Retained Set是指一个对象以及它所有直接或间接引用的对象的集合。如果从GC root删除这个对象,该集合中的所有对象也会被删除。
- Retained Set中的对象都是依赖于特定对象存在的对象。
3.2样例
B
的 Retained Set 包含:B
本身,String
(address
字段),BigDecimal
(longitude
和latitude
字段),BigInteger
及其相关数组。
4.Retained Heap(深堆)
- Retained Heap是指从GC root无法到达该对象时,内存管理器可以回收的总内存大小。它包括了该对象以及所有直接或间接被其引用的对象的Shallow Heap。
- 换句话说,如果某个对象被垃圾回收,导致所有与之相关的对象也将被垃圾回收,那么这些对象的总内存就是Retained Heap。