JVM学习之 如何计算一个类的对象占用的内存

本文的讨论都是基于 HotSpot 虚拟机

对象的内存布局

要知道一个类对象占用的内存,我们就必须要知道对象的内存布局。
对象在堆内存中的存储布局可以划分为三个部分: 对象头,实例数据,对齐填充

对象头

对象的对象头包括两类信息。第一类是存储对象自身的运行时数据,第二类是类型指针

Mark World

存储对象自身的运行时数据,如 哈希码,GC分代年龄、锁状态标志、线程持有的锁等等。这部分的数据长度在32位虚拟机中为4个字节,在64位虚拟机中是8个字节,官方称之为 Mark Word

类型指针

指向它的类型元数据的指针(指向它的Class对象的指针),大小是4个字节。Java虚拟机通过这个指针来确定该对象是哪个类的实例

实例数据

实例数据部分是对象真正存储的有效信息,即我们在程序代码里面所定义的各种类型的字段内容。计算方式是累加,如下对象:

public class O {
    private int o1;
    private long o2
}

实例数据部分长度就是 int(4字节)+long(8字节)=12字节

对齐填充

第三部分就是对齐填充。HotSpot虚拟机的自动内存管理要求对象起始地址必须是8字节的整数倍,换句话说就是任何对象的大小都必须是8字节的整数倍。如果对象大小没到8字节的整数倍,那就需要通过对齐填充来补全。

实战

已经知道了对象的内存布局,我们就可以来尝试计算一个类对象占用的内存:
我们就来计算 String类的内存:

空的String对象:

我们先来查看String类里面的实例数据有哪些;

@Stable
private final byte[] value;
private final byte coder;
private int hash; // Default to 0
private boolean hashIsZero; // Default to false;
 private static final long serialVersionUID = -6849794470754667710L;
static final boolean COMPACT_STRINGS;

可以得到实例数据部分的字节是 数组对象 + byte(1字节)+ int(4字节)+ boolean(1字节) + long(8字节) + Boolean(1字节)

那么数组对象也是一个对象,它的占用内存是 对象头(8字节)+ 引用(4字节)+ 记录长度的int(4字节)=16字节。

所以空的String对象占用内存是 8+16+1+4+1+8+1+ 1字节(字节填充)=40字节

非空的String对象

非空的string对象比空的string对象只有在数组对象里的 实例数据部分变化了,其他都没变,
所以非空的String对象占用内存是 8+16+1+4+1+8+1+ 1字节(字节填充)=40+ n字节(n是byte数组的长度)

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值