【学习笔记】子牙教会我计算Java对象大小

本文探讨了如何计算Java对象在堆区的大小,重点关注开启和关闭指针压缩情况下的对象结构。通过理论分析、实例猜想和JOL工具验证,展示了Object、带有实例数据的对象以及数组对象在64位JVM中的内存布局。
摘要由CSDN通过智能技术生成

硬核子牙公众号原文:你知道如何计算Java的对象大小吗

本文基于子牙老师的讲解,用来记录本人的理解。

一、理论篇

本文计算的是Java对象在 堆区 的大小。学习和掌握该知识,有助于分析“应用系统的堆到底该设置为多大?”的问题。

接着,我整理了一张思维导图,来对对象结构中的各部分大小进行解释:

关于实例数据区域数据大小如下表所示:

数据类型数据长度
boolean1B
byte1B
char2B
int4B
float4B
long8B
double8B
引用类型(开启指针压缩)4B
(关闭指针压缩)8B

二、猜想篇

结合第一章《理论篇》的知识,猜想一下,在64位虚拟机下,Java对象的大小。

目前,主流的服务器基本上都使用的是64位Java虚拟机,因此,接下来计算Java对象大小时,都以此为前提。(不考虑32位虚拟机的情况)

2.1 Object对象大小

Object obj = new Object();
开启指针压缩关闭指针压缩
Mark Word8B8B
Klass Pointer4B8B
实例数据0B0B
对齐填充4B0B
合计16B16B

在64位Java虚拟机下,Mark Word 都为 8B;

开启指针压缩时,因为 8B + 4B + 0B + 0B = 12B,不符合 JVM 所有对象按 8 字节对齐的规则。因此,对象大小扩展到 16B,就可以被 8 整除了。此时,对齐填充的大小等于 4B。

2.2 包含实例数据的对象

public class ObjectWithInstanceData {
  private int a = 10;
  private double b = 10.0d;
}
开启指针压缩关闭指针压缩
Mark Word8B8B
Klass Pointer4B8B
实例数据12B12B
对齐填充0B4B
合计24B32B

2.3 数组对象

int[] array = {1,2,3};
开启指针压缩关闭指针压缩
Mark Word8B8B
Klass Pointer4B8B
数组长度4B4B
对齐填充(数组对象才有的)0B4B
实例数据12B12B
对齐填充4B4B
合计32B40B

三、验证篇

3.1 指针压缩的 JVM 参数

指针压缩的 JVM 参数:

# 开启指针压缩(JVM默认开启的)
-XX:+UseCompressedOops
# 关闭指针压缩
-XX:-UseCompressedOops

3.2 借助 jol-core

这是在代码中打印对象大小的方法。在 Maven 项目的 pom.xml 中引入依赖:

<dependency>
      <groupId>org.openjdk.jol</groupId>
      <artifactId>jol-core</artifactId>
      <version>0.16</version>
</dependency>

打印对象大小的 API 是

String value = ClassLayout.parseInstance(obj).toPrintable();
System.out.println(value);

我索性一口气都打印出来:

import org.openjdk.jol.info.ClassLayout;

public class ObjectWithInstanceData {

    private int a = 10;
    private double b = 10.0d;

    public static void main(String[] args) {
        Object obj = new Object();
        String value = ClassLayout.parseInstance(obj).toPrintable();
        System.out.println(value);

        obj = new ObjectWithInstanceData();
        value = ClassLayout.parseInstance(obj).toPrintable();
        System.out.println(value);

        obj = new int[]{1,2,3};
        value = ClassLayout.parseInstance(obj).toPrintable();
        System.out.println(value);
    }
}

开启指针压缩的 Object 对象结构:

开启指针压缩的 ObjectWithInstanceData 对象结构:

开启指针压缩的 int 数组对象结构:

(array length) 和 (alignment/padding gap) 的 OFFSET 和 SZ 相同,占据同一块内存,因此也可以说是对齐字节为 0

关闭指针压缩的 Object 对象结构:

关闭指针压缩的 ObjectWithInstanceData 对象结构:

关闭指针压缩的 int 数组对象结构:

(array length) 和 (alignment/padding gap) 的 OFFSET 相同,从内存相同位置开始,(alignment/padding gap) SZ 比 (array length) SZ 多 4 个字节,因此也可以说是对填充齐字节为 4。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值