猜猜我的有多大 之 java对象大小

在Java中,对象的大小并不是固定的,它取决于几个因素,包括对象中的数据类型、对象头的大小、对齐填充(padding)以及继承的字段。下面是一些用于估算Java对象大小的基本准则:

  1. 对象头(Object Header): 每个Java对象都有一个对象头,它包含了一些用于管理对象的元数据,比如哈希码、GC分代年龄、锁状态标志、线程持有的锁、偏向线程ID、偏向时间戳等。在32位JVM上,对象头通常是8字节,而在64位JVM上(没有使用压缩指针的情况下)是16字节。

  2. 实例数据(Instance Data): 对象中每个字段的大小取决于其类型。例如,int 是4字节,long 是8字节,引用(在使用压缩指针的64位JVM上)通常是4字节等。

  3. 对齐填充(Alignment Padding): JVM通常要求对象的大小是8字节的倍数。如果对象的大小不是8的倍数,那么就会添加填充以达到这个要求。

为了计算一个对象的大小,你可以遵循以下步骤:

  1. 计算对象头的大小。
  2. 为对象中的每个字段加上相应的大小。
  3. 如果需要,加上对齐填充。

 

Java中的对象对齐填充(Alignment Padding)是由于Java虚拟机(JVM)在内存分配时要求对象的大小必须是一定的倍数(通常是8字节)。这是为了提高性能,因为现代硬件和操作系统通常以这样的边界对齐访问内存更高效。当对象的实际大小不是对齐基数(如8字节)的倍数时,JVM会添加额外的字节以确保对象的总大小是对齐基数的倍数。这些额外的字节就是对齐填充。

对齐填充的情况通常发生在以下几个时候:

  1. 对象头之后:在对象头和实例数据之间,如果对象头的大小加上特定的字段大小不能整除对齐基数,JVM将会在字段之前添加填充。

  2. 字段之间:对于对象中的字段,如果前一个字段的大小加上其地址偏移不能整除对齐基数,则在该字段和下一个字段之间可能会添加填充。

  3. 对象末尾:在对象的最后一个字段之后,如果所有字段的总大小加上对象头的大小不能整除对齐基数,JVM将会添加填充以确保整个对象的大小是对齐基数的倍数。

举个例子:

public class Example {
    char c; // 2 bytes
    int i;  // 4 bytes
}

在一个64位JVM上,如果没有开启压缩指针,则对象头通常是16字节。那么对于上面的Example类:

  • 对象头: 16字节
  • char c: 2字节
  • 填充: 2字节(因为int类型需要4字节对齐,所以在charint之间添加2字节的填充)
  • int i: 4字节

总计:16 + 2 + 2 + 4 = 24字节。由于24字节已经是8的倍数,所以对象末尾不需要额外的填充。

请注意,这些都是理论上的计算,实际的对象布局可能会因JVM的具体实现和版本而有所不同。使用专业工具(如JOL)可以帮助你准确地了解特定JVM上对象的内存布局。

然而,这只是一个粗略的估算。实际对象大小可能因JVM实现的不同而有所变化。如果你需要精确计算对象的大小,可以使用一些工具和技术,比如:

  • 使用Instrumentation接口。Java提供了一个Instrumentation接口,可以用来在运行时查询对象的大小。为了使用它,你需要启用一个Java代理,该代理在JVM启动时加载。
import java.lang.instrument.Instrumentation;

public class ObjectSizeFetcher {
    private static volatile Instrumentation instr;

    public static void premain(String args, Instrumentation inst) {
        instr = inst;
    }

    public static long getObjectSize(Object o) {
        if (instr == null) {
            throw new IllegalStateException("Instrumentation is null");
        }
        return instr.getObjectSize(o);
    }
}

你需要在JVM启动时指定这个代理,使用如下参数:

-javaagent:path/to/agent.jar
  • 使用第三方库。例如,Eclipse Memory Analyzer (MAT) 或 JOL (Java Object Layout) 可以帮助你分析对象在内存中的布局。

  • 使用JVM工具。例如,jmap 可以用来生成堆转储,然后可以用 jhat 或 MAT 分析这个转储。

需要注意的是,对象的实际内存使用还会涉及到其他因素,例如JVM内部的数据结构、GC算法的细节等。

  • 10
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值