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

64位VM未开启指针压缩导致-8内存对齐的疑问

问题

使用JOL工具分析对象内存布局时,配置64位VM未开启指针压缩,运行测试代码后结果显示出现-8内存对齐损失,无法理解该现象成因。

Maven依赖(pom.xml)

<dependency>
    <groupId>org.openjdk.jol</groupId>
    <artifactId>jol-core</artifactId>
    <version>0.10</version>
</dependency>

测试代码

public class MyObjectData {

    private int i=66;
    private long l=6L;
    private String string=new String("aaaa");

}

public class ObjectTest {

    @Test
    public void test1() {
        Layouter l;
        // 64位VM,未开启指针压缩
        l = new HotSpotLayouter(new X86_64_DataModel());
        System.out.println("***** " + l);
        System.out.println(ClassLayout.parseInstance(new MyObjectData(), l).toPrintable());
        System.out.println("===============================================");
    }

}

运行结果

OFFSET  SIZE               TYPE DESCRIPTION                               VALUE
      0     4                    (object header)                           01 00 00 00 (00000001 00000000 00000000 00000000) (1)
      4     4                    (object header)                           00 00 00 00 (00000000 00000000 00000000 00000000) (0)
      8     4                    (object header)                           01 23 01 f8 (00000001 00100011 00000001 11111000) (-134143231)
     12     4                    (object header)                           42 00 00 00 (01000010 00000000 00000000 00000000) (66)
     16     8               long MyObjectData.l                            6
     24     4                int MyObjectData.i                            66
     28     4                    (alignment/padding gap)
     32     8   java.lang.String MyObjectData.string                       (object)
     40    -8                    (loss due to the next object alignment)
Instance size: 32 bytes
Space losses: 4 bytes internal + -8 bytes external = -4 bytes total
分析与解答

这个负的外部对齐损失是JOL特有的统计逻辑,本质不是真的“损失”,而是表示当前对象的末尾刚好满足下一个对象的对齐要求,省去了后续对象需要的对齐填充空间,相当于空间收益。

具体拆解:

  1. 64位无指针压缩的HotSpot对齐规则:对象起始地址必须是8字节的倍数,单个对象的总大小也会对齐到8字节的倍数。
  2. 当前对象内存布局细节:
    • 对象头占16字节(无指针压缩时,Mark Word+Klass Pointer合计16字节)
    • long l占8字节(偏移到16-24字节)
    • int i占4字节(偏移到24-28字节)
    • 内部填充4字节(偏移28-32字节):为了让后续的8字节引用类型字段(string)能对齐到8字节边界
    • String string引用占8字节(偏移32-40字节)
  3. 负损失的由来:
    JOL的“external loss”(外部损失)统计的是当前对象结束后,下一个对象为了满足对齐要求需要额外填充的字节数。如果当前对象的总大小是8的倍数(这里是40字节),下一个对象可以直接从40字节地址开始,不需要任何填充。JOL用-8表示:相比“当前对象结束在非对齐地址,下一个对象需要填充8字节”的情况,现在节省了8字节空间,所以用负数标识这种“反向损失”(即收益)。

另外,结果里的4字节内部损失是int i之后填充的4字节,用来保证后续8字节引用字段的对齐,属于正常的内部对齐填充。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.25 17:08:14