bigywater.tech
Java · 300

JOL 对象布局:看到对象头和对齐填充

一个 Java 对象到底占多少字节?字段怎么排?压缩指针与对齐设置改变什么?JDK 27 的紧凑对象头省多少?这篇用 JOL 看布局,再用真实堆占用核对。

12 字节
JDK 21 默认的对象头大小(8 字节 mark + 4 字节压缩类指针)
72 字节
HashMap 每项(含 Integer 键与值)的深度大小
27.89 → 19.89
JDK 27 紧凑对象头对 Q{int x; int y} 实测每实例字节数的影响

对象布局

实测 · 本机执行输出
  -- Object:实例大小 16 字节
  -- Empty:实例大小 16 字节
  -- A:实例大小 32 字节
     偏移 12 大小 4 int i
     偏移 16 大小 8 long l
     偏移 24 大小 1 byte b
     偏移 28 大小 4 java.lang.Object o
  -- Integer:实例大小 16 字节
     偏移 12 大小 4 int value
  -- Long:实例大小 24 字节
     偏移 16 大小 8 long value
  -- Boolean:实例大小 16 字节
     偏移 12 大小 1 boolean value
  -- 数组头:int[0] 实例大小 16;byte[1] 24;byte[8] 24;byte[9] 32;long[3] 40;Object[3] 32
  [0   8                    (object header: mark)     N/A, 8   4                    (object header: class)    N/A, 25   3                    (alignment/padding gap), Instance size: 32 bytes, Space losses: 3 bytes internal + 0 bytes external = 3 bytes total]

字段排布

实测 · 本机执行输出
  -- P(声明顺序见源码):实例大小 24
     ps@12 pb@14 pl@16
  -- C(声明顺序见源码):实例大小 40
     ps@12 pb@14 cb@15 pl@16 ci@24 cc@28 cz@30 co@32
  -- D(声明顺序见源码):实例大小 48
     i1@12 l1@16 d1@24 f1@32 s1@36 c1@38 z2@40 b1@41 z1@42 o1@44
  声明顺序:P: pb, pl, ps;C: cb, ci, co, cz, cc;D: z1, b1, s1, c1, i1, f1, l1, d1, o1, z2

JVM 选项

实测 · 本机执行输出
  默认                                 A 实例大小 32;字段 i@12 l@16 b@24 o@28 ;Object[3] 32;Integer 16;int[0] 16;Long 24;Q{int x; int y} 24
  -XX:-UseCompressedOops             A 实例大小 40;字段 i@12 l@16 b@24 o@32 ;Object[3] 40;Integer 16;int[0] 16;Long 24;Q{int x; int y} 24
  -XX:-UseCompressedClassPointers    A 实例大小 40;字段 l@16 i@24 b@28 o@32 ;Object[3] 40;Integer 24;int[0] 24;Long 24;Q{int x; int y} 24
  两个都关                               A 实例大小 40;字段 l@16 i@24 b@28 o@32 ;Object[3] 48;Integer 24;int[0] 24;Long 24;Q{int x; int y} 24
  -XX:ObjectAlignmentInBytes=16      A 实例大小 32;字段 i@12 l@16 b@24 o@28 ;Object[3] 32;Integer 16;int[0] 16;Long 32;Q{int x; int y} 32
  -Xmx33g(超过压缩指针上限)                  A 实例大小 40;字段 i@12 l@16 b@24 o@32 ;Object[3] 40;Integer 16;int[0] 16;Long 24;Q{int x; int y} 24
  -Xmx31g                            A 实例大小 32;字段 i@12 l@16 b@24 o@28 ;Object[3] 32;Integer 16;int[0] 16;Long 24;Q{int x; int y} 24

集合的大小

实测 · 本机执行输出
  int[1000]                                  4016 字节(每元素 4.0)
  Integer[1000](装箱,值 1000..1999)            20016 字节(每元素 20.0)
  ArrayList<Integer> 1000 个                 20976 字节(每元素 21.0)
  LinkedList<Integer> 1000 个                40032 字节(每元素 40.0)
  HashMap<Integer,Integer> 1000 项           72256 字节(每元素 72.3)
  HashSet<Integer> 1000 个                   56288 字节(每元素 56.3)
  TreeMap<Integer,Integer> 1000 项           72048 字节(每元素 72.0)
  String "hello"                               48 字节(每元素 48.0)
  String 200 个字符的 Latin-1 字符串                 240 字节(每元素 240.0)

实测堆占用

实测 · 本机执行输出
  JDK 21 默认                        类 A:每个实例实测 34.85 字节
  JDK 21 默认                        类 Q:每个实例实测 26.85 字节
  JDK 21 -XX:-UseCompressedOops    类 A:每个实例实测 46.85 字节
  JDK 21 -XX:-UseCompressedOops    类 Q:每个实例实测 30.85 字节

JDK 27 的对象头

实测 · 本机执行输出
  JDK 21 默认                              偏移 ['A b@24 i@12 l@16 o@28', 'Q x@12 y@16', '数组数据起点 int[] 16,Object[] 16'];实测每个实例 A 34.85 字节,Q 26.85 字节
  JDK 27 默认                              偏移 ['A b@20 i@16 l@8 o@24', 'Q x@8 y@12', '数组数据起点 int[] 12,Object[] 12'];实测每个实例 A 35.89 字节,Q 19.89 字节
  JDK 27 -XX:-UseCompactObjectHeaders    偏移 ['A b@24 i@12 l@16 o@28', 'Q x@12 y@16', '数组数据起点 int[] 16,Object[] 16'];实测每个实例 A 35.89 字节,Q 27.89 字节
  JDK 27 -XX:+UseCompactObjectHeaders    偏移 ['A b@20 i@16 l@8 o@24', 'Q x@8 y@12', '数组数据起点 int[] 12,Object[] 12'];实测每个实例 A 35.89 字节,Q 19.89 字节

分步演示

JOL 对象布局
本步的对象

    本文用到的工具与边界

    • 本机 macOS 27 arm64 / OpenJDK(Temurin 17.0.20、Homebrew 21.0.12 与 27,每篇注明实际用的版本);用 javac 编译、java 直接运行,需要第三方库时用 Maven 解析依赖;计时用 System.nanoTime,数字每次运行会有小幅抖动。JOL 0.17(需要 -Djol.skipHotspotSAAttach=true:否则它尝试用 HotSpot Serviceability Agent 附加自身,在本机上进程会被挂起);JDK 21.0.12 与 27
    • 没有验证:JOL 对 JDK 27 紧凑对象头的支持(JDK 27 的布局用 Unsafe 读取)、实测比预测小约 1.15 字节的原因、其它 GC 下的对象大小、Valhalla 值类型、Linux 与 x86、ObjectAlignmentInBytes=16 下的实测堆占用
    京ICP备2026067502号-1京公网安备11010502063487号