为了更好的理解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 |
除此之外:针对以上所有的数据类型 当它作为数组类型时,消耗字节大小一致的。
定义:在计算对象的Shallow 大小,考虑对象本身包含的大小
例如 :Student这个对象
Student Shallow Size =对象本身 Size【header部分+padding】+对象属性引用本身 Size
定义一个简单类:
//材料类
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 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 VALUE0 8 (object header: mark) 0x0000000000000001 (non-biasable; age: 0)8 4 (object header: class) 0xf800c14312 1 boolean SecurityDoor.lockFlag false13 3 (alignment/padding gap) 16 4 java.lang.String SecurityDoor.metaType null20 4 org.openjdk.jol.samples.domain.Material SecurityDoor.material null24 4 java.util.List SecurityDoor.list null28 4 (object alignment gap)
Instance size: 32 bytes
Space losses: 3 bytes internal + 4 bytes external = 7 bytes totalProcess finished with exit code 0
分析
按照我们分析如下:
一共占用 字节 12 + 1+12=25 ,由于VM 要求字节填充是8的整数倍 ,在填充 8字节刚到达到 32 bytes
定义:对象的深度大小:Shallow Size+所有引用依赖对象的Size
当然 这个对象深度大小是跟 对象的复杂度相关的,如果对象 可达性越来越复杂 他们的深度大小越来越大
还是上述 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 VALUE0 8 (object header: mark) 0x0000000000000001 (non-biasable; age: 0)8 4 (object header: class) 0xf800c18412 1 boolean SecurityDoor.lockFlag false13 3 (alignment/padding gap) 16 4 java.lang.String SecurityDoor.metaType null20 4 org.openjdk.jol.samples.domain.Material SecurityDoor.material (object)24 4 java.util.List SecurityDoor.list null28 4 (object alignment gap)
Instance size: 32 bytes
Space losses: 3 bytes internal + 4 bytes external = 7 bytes totalSecurityDoor 中 material 字符串Description Shallow 对象大小布局:
java.lang.String object internals:
OFF SZ TYPE DESCRIPTION VALUE0 8 (object header: mark) 0x0000000000000001 (non-biasable; age: 0)8 4 (object header: class) 0xf80002da12 4 char[] String.value [1, 2, 3, 4, 5, 6, 7, 8, 9, 0]16 4 int String.hash 020 4 (object alignment gap)
Instance size: 24 bytes
Space losses: 0 bytes internal + 4 bytes external = 4 bytes totalmaterial 字符串Description 中char Shallow 对象大小布局:
[C object internals:
OFF SZ TYPE DESCRIPTION VALUE0 8 (object header: mark) 0x0000000000000001 (non-biasable; age: 0)8 4 (object header: class) 0xf800004112 4 (array length) 1016 20 char [C. N/A36 4 (object alignment gap)
Instance size: 40 bytes
Space losses: 0 bytes internal + 4 bytes external = 4 bytes total
结果分析
SecurityDoor Deep Object 大小:
当前对象 Deep Object Size 对象大小:32+24+40= 96 bytes
定义:当 GC 回收对象占用的内存时,它会释放特定数量的内存。该数量是该对象的Retained大小。
GC Student 实例 A 和 age 无法访问,但 Card 仍然可以通过 Student-B对象访问到。
Card 被 Student-B 对象引用因此不参与释放大小。
因此保留大小计算 一般 会在 Shallow 、Deep Object Size 之间。