🔥深入理解JVM干货教学 - 【Shallow、Retained 、Deep Object Size 计算】
1、常用基本数据类型大小
为了更好的理解JVM 计算大小,我们先看一下我们Java 常用的每种常见类型消耗占用的空间要求 如下:
PS:32 bit-VM 或者 64bit-VM 【存在压缩指针】消耗大小一致
类型 | 消耗bytes |
---|---|
对象引用 | 4 bytes |
boolean | 2 bytes |
short、char | 4 bytes |
int、float | 4 bytes |
long、double | 8 bytes |
除此之外:针对以上所有的数据类型 当它作为数组类型时,消耗字节大小一致的。
2、Shallow、Deep、Retained Object 是什么?
1.1、Shallow Size
定义:在计算对象的Shallow 大小,考虑对象本身包含的大小
例如 :Student这个对象
Student Shallow Size =对象本身 Size【header部分+padding】+对象属性引用本身 Size
1.1.1、举个例子
定义一个简单类:
//材料类
public class Material {
private String description;
public String getDescription() {
return description;
}
public void setDescription(String description) {
this.description = description;
}
public Material(){
}
public Material(String description){
this.description=description;
}
}
//拥有者
public class Owner {
private long id;
}
//安全门 包含 拥有者ID、材料描述 、类型
public class SecurityDoor {
private String metaType;
private boolean lockFlag;
private Material material;
private List<Owner> list;
public Material getMaterial() {
return material;
}
public void setMaterial(Material material) {
this.material = material;
}
}
-------------------------------------
public static void main(String[] args) {
Material material=new Material("1234567890");
SecurityDoor securityDoor =new SecurityDoor();
securityDoor.setMaterial(material);
System.out.println(ClassLayout.parseInstance(securityDoor).toPrintable());
}
SecurityDoor Shallow 大小结果
org.openjdk.jol.samples.domain.SecurityDoor object internals:
OFF SZ TYPE DESCRIPTION VALUE
0 8 (object header: mark) 0x0000000000000001 (non-biasable; age: 0)
8 4 (object header: class) 0xf800c143
12 1 boolean SecurityDoor.lockFlag false
13 3 (alignment/padding gap)
16 4 java.lang.String SecurityDoor.metaType null
20 4 org.openjdk.jol.samples.domain.Material SecurityDoor.material null
24 4 java.util.List SecurityDoor.list null
28 4 (object alignment gap)
Instance size: 32 bytes
Space losses: 3 bytes internal + 4 bytes external = 7 bytes total
Process finished with exit code 0
分析
按照我们分析如下:
- String、Material、Owner 3个对象引用,每个占用 4 个字节。3*4=12 bytes
- 一个 占用 1 bytes 的 boolean
- 对象Header 占用 12 bytes 【不清楚参考 为什么12 bytes 参考 如下文章 深入理解JVM干货教学 - 【Java对象结构】
】
一共占用 字节 12 + 1+12=25 ,由于VM 要求字节填充是8的整数倍 ,在填充 8字节刚到达到 32 bytes
1.2、Deep Object Size
定义:对象的深度大小:Shallow Size+所有引用依赖对象的Size
当然 这个对象深度大小是跟 对象的复杂度相关的,如果对象 可达性越来越复杂 他们的深度大小越来越大
1.2.1、举个例子
还是上述 SecurityDoor类,我们在对象中设置一个 Material 对象值
public static void main(String[] args) {
Material material=new Material("1234567890");
SecurityDoor securityDoor =new SecurityDoor();
securityDoor.setMaterial(material);
System.out.println(" SecurityDoor Shallow 对象大小布局:");
System.out.println(ClassLayout.parseInstance(securityDoor).toPrintable());
System.out.println("SecurityDoor 中 material 字符串Description Shallow 对象大小布局:");
System.out.println(ClassLayout.parseInstance(material.getDescription()).toPrintable());
System.out.println(" material 字符串Description 中char Shallow 对象大小布局:");
System.out.println(ClassLayout.parseInstance(material.getDescription().toCharArray()).toPrintable());
}
执行结果
org.openjdk.jol.samples.domain.SecurityDoor object internals:
OFF SZ TYPE DESCRIPTION VALUE
0 8 (object header: mark) 0x0000000000000001 (non-biasable; age: 0)
8 4 (object header: class) 0xf800c184
12 1 boolean SecurityDoor.lockFlag false
13 3 (alignment/padding gap)
16 4 java.lang.String SecurityDoor.metaType null
20 4 org.openjdk.jol.samples.domain.Material SecurityDoor.material (object)
24 4 java.util.List SecurityDoor.list null
28 4 (object alignment gap)
Instance size: 32 bytes
Space losses: 3 bytes internal + 4 bytes external = 7 bytes total
SecurityDoor 中 material 字符串Description Shallow 对象大小布局:
java.lang.String object internals:
OFF SZ TYPE DESCRIPTION VALUE
0 8 (object header: mark) 0x0000000000000001 (non-biasable; age: 0)
8 4 (object header: class) 0xf80002da
12 4 char[] String.value [1, 2, 3, 4, 5, 6, 7, 8, 9, 0]
16 4 int String.hash 0
20 4 (object alignment gap)
Instance size: 24 bytes
Space losses: 0 bytes internal + 4 bytes external = 4 bytes total
material 字符串Description 中char Shallow 对象大小布局:
[C object internals:
OFF SZ TYPE DESCRIPTION VALUE
0 8 (object header: mark) 0x0000000000000001 (non-biasable; age: 0)
8 4 (object header: class) 0xf8000041
12 4 (array length) 10
16 20 char [C.<elements> N/A
36 4 (object alignment gap)
Instance size: 40 bytes
Space losses: 0 bytes internal + 4 bytes external = 4 bytes total
结果分析
SecurityDoor Deep Object 大小:
- SecurityDoor 本身 Shallow size :32 bytes
- Material 对象中有一个 每个 String 对象,【String都封装了一个 char[] 】 24 bytes
- 查看String对象中 char[] 数组的大小 40 bytes 【PS:JDK9 封装的 bytes[] 因此这个大小可能会受到影响 】
当前对象 Deep Object Size 对象大小:32+24+40= 96 bytes
1.3、Retained Object Size
定义:当 GC 回收对象占用的内存时,它会释放特定数量的内存。该数量是该对象的Retained大小。
GC Student 实例 A 和 age 无法访问,但 Card 仍然可以通过 Student-B对象访问到。
Card 被 Student-B 对象引用因此不参与释放大小。
因此保留大小计算 一般 会在 Shallow 、Deep Object Size 之间。