JAVA——对象所占内存空间大小的计算

本文探讨了Java中对象内存空间的分配,强调了8字节对齐规则,并详细解析了对象头、实例数据和填充部分的内存组成。通过示例展示了如何计算包括祖先类在内的对象总大小,并提供了实验环境和步骤。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

学过c++的朋友想必对“c++的内存对齐规则”不会感到陌生。那么在java中,是否也存在这样的规则呢?为此,笔者进行了实验,发现java的内存对齐规则非常简明——8字节对齐。现与大家分享下。
一个java对象所占的内存空间分为三个部分:对象头(Mark Word+类型指针+长度)+实例数据+填充。
填充的目的是保证一个java对象的大小是8B的整数倍。
对象头分为三个部分:Mark Word、类型指针和长度。这三个部分所占内存空间大小如下所示:

项目 占用的内存大小 说明
Mark Word 4B/32位, 8B/64位
类型指针 4B/32位, 8B/64位
长度 4B/32位, 8B/64位 仅数组对象才会有这一部分

接下来说一下实例数据包括哪些。静态成员变量或静态成员常量是属于整个类的,存储在方法区,所以不包括在内;当前类所实现接口中的常量,是静态的,同样存储在方法区,不包括在内;所有的方法,不管是静态的还是非静态的,也存储在方法区,不包括在内。剩下的实例成员变量或实例成员常量(包括其祖先类的)就是每个对象要存储的数据 。这些实例成员所占的内存空间大小如下所示:

类型 占用的内存大小 说明
boolean 1B 与平台无关
byte 1B 与平台无关
short 2B 与平台无关
char 2B 与平台无关
int 4B 与平台无关
float 4B 与平台无关
long 8B 与平台无关
double 8B 与平台无关
reference 4B/32位,8B/64位

具体计算方式如下:
假设当前类为B,其父类为A3,类A3的父类为A2,类A2的父类为A1,类A1的父类是Object,且类B, A3, A2, A1都仅有一个char c;成员变量(当然,这仅仅是举例说明而已,实际情况下可更复杂或更简单),用S_XXX表示类XXX中实例成员的总大小(不包括其祖先类的)。那么类B的一个对象b所占据的内存大小(包括祖先类的)sizeof_b为:

sizeof_b=对象头+(S_A1+填充S_A1)+(S_A2+填充S_A2)+(S_A3+填充_S_A3)+(S_B+填充_S_B)

“填充_S_XXX”的目的是保证从“对象头”到类XXX部分之和为8B的整数倍。注意看啊,这里每个类都是要填充的,而不是仅在最后才填充,这样做也方便强制类型转换后的处理。而且类XXX中成员变量的声明顺序不影响“S_XXX”的值。
上述类B的一个对象b所占用的内存结构图(32位机器上)如下所示:
这里写图片描述

又比如“new int[4]”这个对象在32位机器上所占用的内存为:
这里写图片描述

再比如这个对象在32位机器上所占用的内存情况为:
这里写图片描述

下面给出笔者的实验步骤。先是编写两个类SizeOfObjectTest和SizeOfAgent;然后将代码(使用Ant工具)打成可执行的jar包(如 jvm-project.jar,主类是SizeOfObjectTest),最后在命令行里输入如下命令运行该jar包即可查看结果:

java -javaagent:jvm-project.jar -XX:-UseCompressedOops -jar jvm-project.jar

本文仅仅讨论未使用指针压缩情况下的占用内存大小情况。
类SizeOfAgent的编写以及运行方式均是参考http://yueyemaitian.iteye.com/blog/2033046
下面分别给出SizeOfObjectTest类、SizeOfAgent类和打包脚本。

SzieOfObjectTest类的代码:


package quote;

import java.io.File;

/**
 * @author tianmai.fh
 * @date 2014-03-18 20:17
 */
public class SizeOfObjectTest {
   
   
    /**
     *
     * -XX:-UseCompressedOops: mark/8 + metedata/8 + 8 + padding/0 = 24
     */
    static class A {
   
   
        int a;
        char c;
    }



    static class A2{
   
   
        char b;
        int a;
    }

    static class A3{
   
   
        char b;
        boolean c;
        double d;
        short e;
        boolean f;
    }

    static class A4{
   
   
        char b;
        short e;
        boolean d;
        boolean f;
        double a;
    }

    static class A5{
   
   
        int[] b=new int[10];
    }

    /**
     * -XX:+UseCompressedOops: mark/4 + metedata/8 + 4 + 4 + padding/4 = 24
     * -XX:-UseCompressedOops: mark/8 + metedata/8 + 4 + 4 = 24
     */
    static class B {
   
   
        int a;
        int b;
    }

    /**
     * -XX:+UseCompressedOops: mark/4 + metedata/8 +
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值