一个Java对象到底占用多大内存?

本文详细分析了Java对象在JVM中的内存占用,包括对象头(Mark Word和类型指针)、实例数据以及对齐填充。讨论了64位虚拟机的指针压缩,并给出了计算对象大小的理论方法。通过Instrumentation工具验证了理论计算,展示了如何使用javaagent技术计算对象的实际大小。
摘要由CSDN通过智能技术生成

  在进行 JVM 调优时,我们经常关注 JVM 各个区域大小以及相关参数,从而进行特定的优化,在一次排查内存溢出问题时我不禁想到一个问题,一个 Java 对象到底占用多大内存?下面我们就来分析验证下。
  
  Java 对象内存结构
  
  在 JVM 中,Java 对象都是在堆内存上分配的,想要分析出 Java 对象内存占用,首先要了解 Java 对象内存结构,一个 Java 对象内存占用由三部分组成:对象头(Header),实例数据(Instance Data)和对齐填充(Padding)。
  
  对象头(Header)
  
  对象头的组成
  
  虚拟机的对象头包括两部分信息,第一部分用于存储对象自身的运行时数据,如 hashCode 、GC分代年龄、锁状态标志、线程持有的锁、偏向线程ID、偏向时间戳等。这部分数据的长度在 32 位和 64 位的虚拟机(未开启指针压缩)中分别为 4B 和 8B ,官方称之为 ”Mark Word”。
  
  对象的另一部分是类型指针(kclass),即对象指向它的类元数据的指针,虚拟机通过这个指针来确定这个对象是那个类的实例。另外如果对象是一个 Java 数组,那在对象头中还必须有一块用于记录数组长度的数据,因为虚拟机可以通过普通 Java 对象的元数据信息确定 Java 对象的大小,但是从数组的元数据中却无法确定数组的大小。同样,这部分数据的长度在 32 位和 64 的虚拟机(未开启指针压缩)中分别为 4B 和 8B。
  
  指针压缩
  
  从 JDK 1.6 update14 开始,64 bit JVM 正式支持了 -XX:+UseCompressedOops 这个可以压缩指针,起到节约内存占用的新参数。
  
  如果 UseCompressedOops 是打开的,则以下对象的指针会被压缩:
  
  所有对象的 klass 属性
  
  所有对象指针实例的属性
  
  所有对象指针数组的元素(objArray)
  
  由此我们可以计算出对象头大小:
  
  32位虚拟机对象头大小= Mark Word(4B)+ kclass(4B) = 8B
  
  64位虚拟机对象头大小= Mark Word(8B)+ kclass(4B) = 12B
  
  实例数据
  
  一个 Java 对象中的实例数据可能包括两种,一是 8 种基本类型,二是实例数据也是一个对象,说到这里很多人可能有个误区:
  
  基本类型?基本类型不是在栈上分配内存的吗?怎么要计算到分配在堆内存上对象的大小里面去?
  
  基本类型在栈上分配内存?其实并不是,所谓“栈内存保存基本类型以及对象的引用(reference),堆内存保存对象” 只是一句不严谨的话,实际仔细研究起来,栈内存(更专业的术语叫做堆栈)作为虚拟机作为方法调用和方法执行的数据结构,可能保存五种信息:
  
  局部变量表
  
  操作数栈
  
  动态链接
  
  方法返回地址
  
  附加信息
  
  其中局部变量表中存储了方法中的局部变量,可能为 8 种基本类型或者 reference
  
  也就是说,栈内存中保存的基本类型,都是方法中的局部变量,而如果基本类型作为对象的实例变量,是在堆上分配空间的,此外,如果实例变量被final修饰,则既不在栈也不在堆上分配空间,而是分配到常量池里面。
  
  8 种基本类型和 reference 大小在虚拟机上都是固定的,见下表
  
  Primitive Type    Memory Required(bytes)
  
  boolean    1
  
  byte    1
  
  short    2
  
  char    2
  
  int    4
  
  float    4
  
  long    8
  
  double    8
  
  Reference    4
  
  对齐填充(Padding)
  
  由于虚拟机内存管理体系要求 Java 对象内存起始地址必须为 8 的整数倍,换句话

  • 0
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值