如何获取Java对象的大小

1. 使用 java.lang.instrument.Instrumentation(精确计算)

这是最准确的方法,但需要通过Java Agent来实现:

  1. 创建一个Java Agent类
import java.lang.instrument.Instrumentation;

public class ObjectSizeAgent {
    private static volatile Instrumentation globalInstrumentation;

    public static void premain(String agentArgs, Instrumentation inst) {
        globalInstrumentation = inst;
    }

    public static long getObjectSize(Object obj) {
        if (globalInstrumentation == null) {
            throw new IllegalStateException("Instrumentation not initialized");
        }
        return globalInstrumentation.getObjectSize(obj);
    }
}
  1. 配置 MANIFEST.MF

    • MANIFEST.MF 中添加:
      Premain-Class: com.example.ObjectSizeAgent
      
  2. 打包为JAR并运行

    java -javaagent:objectsizeagent.jar YourMainClass
    
  3. 在代码中使用

public class Main {
    public static void main(String[] args) {
        MyClass obj = new MyClass();
        long size = ObjectSizeAgent.getObjectSize(obj);
        System.out.println("Object size: " + size + " bytes");
    }
}

2. 使用第三方库(简化实现)

2.1. jol-core(Java Object Layout)

由OpenJDK团队开发,可直接计算对象大小:

import org.openjdk.jol.info.ClassLayout;

public class ObjectSizeCalculator {
    public static void main(String[] args) {
        MyClass obj = new MyClass();
        System.out.println(ClassLayout.parseInstance(obj).toPrintable());
    }
}

依赖(Maven):

<dependency>
    <groupId>org.openjdk.jol</groupId>
    <artifactId>jol-core</artifactId>
    <version>0.16</version>
</dependency>
2.2. Apache Commons Lang

SerializationUtils.serialize() 可估算序列化后的大小:

import org.apache.commons.lang3.SerializationUtils;

public class ObjectSizeEstimator {
    public static void main(String[] args) {
        MyClass obj = new MyClass();
        byte[] bytes = SerializationUtils.serialize(obj);
        System.out.println("Serialized size: " + bytes.length + " bytes");
    }
}

3. 手动估算(基于JVM规范)

对象在内存中的结构通常包括:

  • 对象头(Object Header):
    • Mark Word(通常8字节)
    • 类型指针(4或8字节,取决于是否开启指针压缩)
  • 实例数据(Instance Data):字段的实际值
  • 对齐填充(Padding):按8字节对齐

示例计算

class MyClass {
    int a;         // 4字节
    long b;        // 8字节
    String c;      // 引用类型:4或8字节
}
  • 总大小估算
    • 对象头:12字节(8+4,假设开启指针压缩)
    • 实例数据:4(a) + 8(b) + 4(c) = 16字节
    • 对齐填充:4字节(总大小需为8的倍数)
    • 总计:12 + 16 + 4 = 32字节

4. 注意事项

  • 指针压缩(Compressed OOPs)

    • 64位JVM默认开启,对象引用占4字节(否则占8字节)。
    • 通过 -XX:+UseCompressedOops 控制。
  • 数组和集合

    • 数组对象包含额外的长度字段。
    • 集合类(如 ArrayList)需计算内部数组的大小。
  • 静态字段

    • 静态字段不属于对象实例,不计入对象大小。

5. 工具推荐

  • JProfiler:可视化工具,直接查看对象大小。
  • YourKit:支持内存分析和对象大小统计。
  • Eclipse Memory Analyzer (MAT):分析堆转储文件。

总结

  • 精确计算:使用 Instrumentationjol-core
  • 快速估算:手动计算对象头、字段和对齐填充。
  • 复杂场景:借助专业工具分析堆内存。

一般场景下推荐 方案2

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值