Java对象大小计算

本文探讨了在JVM调优中理解对象大小的重要性,介绍了Java对象的内存布局,包括对象头、实例数据和对齐填充。讲解了如何通过InstrumentationAPI、第三方工具如JOL和VisualVM计算对象大小,以及手动估算的方法。实例演示了如何使用JOL进行内存占用分析。
摘要由CSDN通过智能技术生成

概述

在实际应用中,尤其是在进行JVM调优时,理解并正确估计对象大小是非常重要的,因为这直接影响到内存分配、垃圾回收效率以及应用程序的整体性能。

对象的组成

在Java中,计算一个对象的大小是为了了解它在内存中占用的确切空间。Java对象在Java虚拟机(JVM)中的内存布局主要包括三个部分:

  1. 对象头(Header):
    对象头通常包含用于存储对象自身的运行时元数据,如哈希码、锁状态标志、线程持有的锁指针等信息,这部分称为mark word。
    另外,对象头还可能包含指向类元数据的指针,用于方法调度和类型信息识别。
  2. 实例数据(Instance Data):
    这是对象的实际有效载荷,包括所有字段变量(成员变量)。每个字段根据其类型有不同的大小,基本类型的大小固定,而引用类型的大小则依赖于JVM实现,通常是固定的引用宽度(如32位或64位环境下的4字节或8字节)。
  3. 对齐填充(Padding):
    为了满足特定JVM或操作系统对于内存分配的要求(比如某些硬件平台要求内存地址必须是某个字节数的倍数),JVM会在对象实例数据末尾填充额外的字节,确保整个对象占用的空间是对齐的。

Java中的基本数据类型及其大小

  1. 整数类型:
    byte: 8位(1字节),有符号整数,范围从-128到127。
    short: 16位(2字节),有符号整数,范围从-32,768到32,767。
    int: 32位(4字节),有符号整数,范围从-231到231-1(即-2,147,483,648到2,147,483,647)。
    long: 64位(8字节),有符号整数,范围从-263到263-1。
  2. 浮点类型:
    float: 32位(4字节),单精度浮点数。
    double: 64位(8字节),双精度浮点数。
  3. 字符类型:
    char: 16位(2字节),无符号Unicode字符,范围从\u0000到\uffff。
  4. 布尔类型:
    boolean: 在Java虚拟机中没有明确规定其确切的大小,但通常被视为占据至少一个比特位。然而,在内存分配时,它往往会被编译器优化成字节存储。

需要注意的是,尽管硬件架构可能不同,但在Java虚拟机中,上述基本数据类型的大小是固定的,并不依赖于运行Java程序的具体平台。

计算大小方式

要精确计算Java对象的大小,可以使用以下几种方法:

  • Instrumentation API: Java的java.lang.instrument.Instrumentation 接口提供了诸如getObjectSize()这样的方法,允许在运行时获取对象的精确大小。
  • JDK1.8有一个类jdk.nashorn.internal.ir.debug.ObjectSizeCalculator可以评估出对象的大小,直接调用静态方法ObjectSizeCalculator.getObjectSize
  • 第三方工具: 使用诸如JOL (Java Object Layout) 或 VisualVM 等工具分析堆内存,它们能够展示出对象的具体内存布局以及占用大小。
  • 手动估算: 根据上述组成原理,可以逐个累加各字段的大小来估算对象头加上实例数据的大小,但这种方法很难考虑到具体的JVM实现细节以及对齐填充的影响。

计算大小实战

这里使用第三方工具JOL

import jdk.nashorn.internal.ir.debug.ObjectSizeCalculator;
import org.openjdk.jol.info.ClassLayout;

public class ObjectSize {

    public static void main(String[] args) {
        System.out.println("只打印大小");
        System.out.println(ObjectSizeCalculator.getObjectSize(new Object()));
        System.out.println(ObjectSizeCalculator.getObjectSize(new String()));
        System.out.println(ObjectSizeCalculator.getObjectSize(new int[]{}));
        System.out.println(ObjectSizeCalculator.getObjectSize(new Integer(1)));

        System.out.println("打印对象的内存大小占用情况,详细版本");
        ClassLayout layout = ClassLayout.parseInstance(new Object());
        System.out.println(layout.toPrintable());


        System.out.println();
        ClassLayout layout2 = ClassLayout.parseInstance(new A());
        System.out.println(layout2.toPrintable());

        System.out.println();
        ClassLayout layout1 = ClassLayout.parseInstance(new int[]{});
        System.out.println(layout1.toPrintable());
    }

    public static class A {
        private Integer age;

        private String name;

        private Double balance;

        private Boolean sex;
    }
}

说明

以下对A对象的对象大小进行说明

在这里插入图片描述

总结

理解Java对象大小的重要性、组成以及计算方法,以便更好地进行内存优化和性能调优,欢迎关注:鲁班曰

参考文献

java对象在内存的大小

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值