Java 对象

如果想要了解java对象在内存中的大小,必须先要了解java对象的结构。

HotSpot虚拟机中,对象在内存中存储的布局可以分为三块区域:对象头(Header)、实例数据(Instance Data)和对齐填充(Padding)

java 对象头

  • Mark Word
    HotSpot虚拟机的对象头(Object Header)包括两部分信息,第一部分用于存储对象自身的运行时数据, 如哈希值(HashCode)、GC分代年龄、锁状态标志、线程持有的锁、偏向线程ID、偏向时间戳等等,这部分数据的长度在32位和64位的虚拟机(暂 不考虑开启压缩指针的场景)中分别为32个和64个Bits,官方称它为“Mark Word”。

  • Class Metadata Address
    存储该对象的 Class 对象的地址。就是该对象属于那个Class。

  • ArrayList
    存储数组的长度。
    如果是数组对象才会有此数据。非数组对象没有此数据。

具体对象头占用的大小如下:

长度 内容 说明
32/64 bit Mark Word 存储对象的 hashCode 或锁信息等
32/64 bit Class Metadata Address 存储到对象类型数据的指针
32/64 bit ArrayList 数组的长度(如果当前对象是数组)

从上面表格中,我们可以推断出:

32位系统:

  • 对象头占用:32+32=64bit。 64bit/8=8byte。
  • 数组对象头占用:32+32+32=96bit。 96bit/8=12byte。

64位系统:

对象头占用:64+64=128bit。128bit/8=16byte。
数组对象头占用:64+64+64=192bit。 192bit/8=24byte。

实例数据

实例数据就是,对象中的实例变量。
实例变量类型分为:基本类型和引用类型。

类型 32位系统占用空间 64位系统占用空间
boolean 1 byte 1 byte
byte 1 byte 1 byte
char 2 byte 2 byte
short 2 byte 2 byte
int 4 byte 4 byte
float 4 byte 4 byte
long 8 byte 8 byte
double 8 byte 8 byte
ref 4 byte 8 byte

对齐填充

对象在堆中分配的最新存储单位是8byte。如果存储的数据不够8byte的倍数,则对齐填充够8的倍数个字节。

Java 对象大小分析

下面我们以 64 位的 JDK 进行分析 Java 对象在堆中的占用空间大小

代码示例一

public class StrObj1 {private String a;
}
public class StrObj2 {private String a;private String b;
}
public class StrObj3 {private String a;private String b;private String c;
}
public class StrObj4 {private String a;private String b;private String c;private String d;
}
public class NumObj {private int a;private int b;private int c;private int d;
}
public class Obj {public static void main(String[] args) {Obj obj = new Obj();StrObj1 s1 = new StrObj1();StrObj2 s2 = new StrObj2();StrObj3 s3 = new StrObj3();StrObj4 s4 = new StrObj4();Obj[] arrObj = new Obj[10];NumObj num = new NumObj();//System.gc()  会出发 FullGC。System.gc();}
}

运行程序

java -XX:+HeapDumpBeforeFullGC -XX:HeapDumpPath=D:\hprof\test2.hprof -XX:-UseCompressedOops cn.com.infcn.jmat.ObjectAnalyze

启动参数说明:

-XX:+UseCompressedOops
开启指针压缩。(默认开启,该参数对64位虚拟机有用)
-XX:-UseCompressedOops
关闭指针压缩。
其它参数具体 JVM 参数解释详见:生成 Heap Dump 的几种方式

因为 System.gc(); 会出发FullGC,配合-XX:+HeapDumpBeforeFullGC 参数,会在 FullGC 前会在生成一个堆dump文件:D:\hprof\test2.hprof

分析dump

本案例,使用 jmat 工具进行分析 dump 文件。

cn.com.infcn.jmat.Obj 对象分析

从图中我们发现 cn.com.infcn.jmat.Obj 对象占用 16 byte 空间。
非数组64位的对象头 占用16字节,而且改对象没有属性,16字节正好也是8的倍数,不需要填充,所以占用堆空间久违16字节。

cn.com.infcn.jmat.StrObj1

图中可以看出 cn.com.infcn.jmat.StrObj1 对象占用 24 byte 空间。

对象头 16 byte
1 个引用类型实例变量
16 + 8 = 24 byte

cn.com.infcn.jmat.StrObj2

图中可以看出 cn.com.infcn.jmat.StrObj1 对象占用 32 byte 空间

对象头 16 byte
2 个引用类型实例变量
16 + 2 * 8 = 32 byte

cn.com.infcn.jmat.StrObj3

图中可以看出 cn.com.infcn.jmat.StrObj1 对象占用 40 byte 空间

对象头 16 byte
3 个引用类型实例变量
16 + 3 * 8 = 40 byte

cn.com.infcn.jmat.StrObj4

图中可以看出 cn.com.infcn.jmat.StrObj1 对象占用 48 byte 空间

对象头 16 byte
4个引用类型实例变量
16 + 4 * 8 = 48 byte

cn.com.infcn.jmat.NumObj

图中可以看出 cn.com.infcn.jmat.NumObj 对象占用 32 byte 空间

4个 int 类型实例变量
16 + 4 * 4 = 32 byte

cn.com.infcn.jmat.Obj[] 数组

图中可以看出 cn.com.infcn.jmat.Obj[] 对象占用 104 byte 空间

数组对象头 24 byte
10 个 Obj 的引用。
24 + 8 * 10 = 104 byte

对象数组中存储的是对象的引用,而不是实际的数据。

代码示例 二

public class BooleanObj1 {boolean a;
}......public class BooleanObj8 {boolean a;boolean b;boolean c;boolean d;boolean e;boolean f;boolean g;boolean h;
}
public class BooleanObj9 {boolean a;boolean b;boolean c;boolean d;boolean e;boolean f;boolean g;boolean h;boolean i;
}

以指针非压缩方式执行,然后分析dump。

从图中我们发现 BooleanObj1 和 BooleanObj8 大小一样都是24。
而 BooleanObj9 的大小为32。

BooleanObj1

对象头 16 byte
1 个 boolean 实例变量。

16 + 1 = 17 byte。
因为 17 byte 不是 8 的倍数,需要 对齐填充
所以BooleanObj1 所占空间为 24 byte。

BooleanObj8

对象头 16 byte
8 个 boolean 实例变量。

16 + 8 = 24 byte。

BooleanObj9

对象头 16 byte
9 个 boolean 实例变量

16 + 9 =25 byte
对齐填充 后为 32 byte


想了解更多精彩内容请关注我的公众号

Java 对象占用内存大小相关推荐

  1. java对象占用内存大小?

    一个不包含任何内部成员变量的空Object大约占33byte,若增加成员变量,则增加相应大小的内存占用. 测算方式:设置jvm的堆大小为1m,在堆中不停new不含任何成员变量的OOMObject对象, ...

  2. Java 中对象占用内存大小计算

    原文地址 mp.weixin.qq.com byte 与 bit bit:位,比特.信息的最小单位,二进制数中的一个位数 (二进制位),其值为"0" 或"1": ...

  3. 2020 idea 查看内存消耗_查看运行时某个java对象占用JVM大小及通过idea查看java的内存占用情况...

    一.如果想看运行时某个java对象占用JVM内存大小,可以先将对象转换成字节类型,然后计算: List bizGroupRelatedEventInfos = bizEventVersionMappe ...

  4. Java 获取对象占用内存大小

    1.第一步引入依赖 gradle引入:implementation group: 'org.apache.lucene', name: 'lucene-core', version: '4.0.0'i ...

  5. java 队列占用内存大小_Java线程池队列吃的太饱,撑着了咋整?java 队列过大导致内存溢出...

    Java的Executors框架提供的定长线程池内部默认使用LinkedBlockingQueue作为任务的容器,这个队列是没有限定大小的,可以无限向里面submit任务. 当线程池处理的太慢的时候, ...

  6. 一个Java对象占用多大内存

    ​ 这个问题一般会出现在稍微高端一点的 Java 面试环节.要求面试者不仅对 Java 基础知识熟悉,更重要的是要了解内存模型. Java 对象模型 HotSpot JVM 使用名为 oops (Or ...

  7. JVM对象占用内存计算

    大家都知道,jvm中对象实例存储在堆中,对象的引用存储在栈中,而对象的元数据(类型数据)存储在方法区.在我们进行内存优化的过程中经常需要了解每个对象占用的内存大小.接下来我将介绍对象占用内存大小的计算 ...

  8. java String 最长长度和占用内存大小

    一 序 String在内存中的最大长度理论上是int型变量的最大值,Integer.MAX_VALUE, String的字面常量的最大长度为CONSTANT_Utf8_info表决定,一般为65535 ...

  9. android bitmap 占用内存大小,drawable与bitmap内存占用大小

    1, 比较Drawable与Bitmap占用内存大小 2, 比较BitmapFactory类的decodeResource方法与decodeStream方法的效率 好吧,先来看第1个测试! 以下这个是 ...

最新文章

  1. 计算机多媒体运用的ppt课件,《计算机多媒体》PPT课件.ppt
  2. 比发丝还小的机器人“大军”来了,光照就能行走,10厘米晶圆能造100万个 | Nature...
  3. 查找所有的(字符相同但顺序不同) Find All Anagrams in a String
  4. bzoj 2109 amp; 2535 空中管制 解读
  5. poj 2553 The Bottom of a Graph 未完
  6. vbs发送邮件(win10环境下成功)
  7. java开发cs项目_本硕机械转行cs(java后端开发)上岸之路
  8. 在windows上linux命令行,如何在Windows中通过Cygwin来使用Linux命令行
  9. mysql支持arm64架构吗_ARM架构下面安装mysql5.7.22
  10. RHEL7中设置ssh
  11. Adam自适应矩估计
  12. Ubuntu 20.04 下 MOSEK 9.3 的安装
  13. Metal每日分享,图像阀值素描滤镜效果
  14. 【SpringBoot深入浅出系列】SpringBoot之实现支付宝扫码支付(沙箱环境编码实现)
  15. PV 操作与案例分析
  16. iTop4412---linux 3.0.15内核编译错误
  17. 上海热门共享办公室租赁平台
  18. Accessibility Verification Test--无障碍测试简介
  19. python 股票库_GitHub - zxyxz/stock: stock,股票系统。使用python进行开发。
  20. 如何策划一场App地推活动方案

热门文章

  1. kaggle研究生招生(上)
  2. 被忽视的fuzzywuzzy库
  3. textrank4zh来处理句子的重要度
  4. ​你真正了解使用过的数据集吗?数据集有什么关系?数据集之间有多像?
  5. ​亚马逊出品:非均匀扰动的对抗鲁棒性理论分析
  6. ICPR 2020国际学术竞赛:大规模无噪声精细商品图像识别
  7. 飞桨全新发布,核心框架首次完整公开解读
  8. java笔记类与对象3.7-3.10 2020.3.17
  9. HDU1250 Hat's Fibonacci 大数斐波那契数列
  10. spring boot记录操作日志