You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

为什么Java8环境下char[1024]数组的浅大小为2072字节?

问题截图

内存大小偏差原因

8字节的偏差来自两点:一是你对HotSpot数组对象的内存布局认知有误,错误计入了不存在的引用字段,也没考虑压缩指针开关对对象头大小的影响;二是没有结合当前JVM的实际运行参数计算内存占用。

HotSpot数组对象的内存布局规则

Oracle JDK/OpenJDK默认使用的HotSpot虚拟机,堆中对象的内存分配遵循两个核心规则:

  • 所有对象的内存起始地址必须是8字节的整数倍,对象总大小不足8字节整数倍的部分,会用填充位补齐
  • 数组类型的对象头固定由三部分组成,不存在你提到的单独“引用字段”:
    • Mark Word:固定占8字节,存储对象哈希码、GC分代年龄、锁标记等运行时元数据
    • Klass Pointer:指向对象所属类元数据的指针,开启-XX:+UseCompressedOops(压缩普通对象指针)时占4字节,关闭时占8字节
    • 数组长度字段:int类型,固定占4字节,为数组对象独有
  • 数组的实例数据段就是连续存储的数组元素,char类型每个元素固定占2字节

对应2072字节的实际计算

你当前的JDK 1.8.0_333环境处于关闭压缩对象指针的状态,char[1024]的内存计算过程为:

  1. 对象头大小:8字节Mark Word + 8字节未压缩Klass Pointer + 4字节长度字段 = 20字节
  2. 元素存储大小:1024 * 2 = 2048字节
  3. 对齐填充:20 + 2048 = 2068字节,不是8的整数倍,需要填充4字节到最近的8的倍数,即2072字节,和你在hprof中观测到的结果完全一致。

压缩指针关闭的常见原因

JDK 8默认开启压缩指针,但两种场景下会关闭:

  • 启动JVM时手动指定了-XX:-UseCompressedOops参数
  • 配置的最大堆内存(-Xmx)超过32GB,此时32位偏移量无法覆盖全堆地址空间,HotSpot会自动关闭压缩指针。

你之前算出的2064字节,是开启压缩指针时的char[1024]大小:此时对象头为8+4+4=16字节,加2048字节元素总大小为2064,本身就是8的倍数不需要填充,这也是大多数默认小堆配置下JDK8的常规表现。


内容的提问来源于stack exchange,提问作者CoXier

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.29 20:09:11