Java对象内存结构详解

发布于:2025-04-14 ⋅ 阅读:(28) ⋅ 点赞:(0)

Java对象内存结构详解

Java对象在JVM内存中的存储结构可以分为三个部分:对象头(Header)、实例数据(Instance Data)和对齐填充(Padding)。以下是64位JVM(开启压缩指针)下的典型布局:
在这里插入图片描述

1. 对象头(Header)

对象头包含运行时元数据和控制信息,占12字节(压缩指针)或16字节(未压缩)

(1) Mark Word(8字节)

存储对象自身的运行时数据,内容会随锁状态变化:

锁状态 存储内容
无锁 哈希码(31bit) + 分代年龄(4bit) + 偏向模式(1bit) + 锁标志(2bit)
偏向锁 线程ID(54bit) + Epoch(2bit) + 分代年龄(4bit) + 偏向模式(1bit) + 锁标志(2bit)
轻量级锁 指向栈中锁记录的指针(62bit) + 锁标志(2bit)
重量级锁 指向监视器(Monitor)的指针(62bit) + 锁标志(2bit)
GC标记 空(用于垃圾回收标记)

(2) Klass Pointer(4字节)

指向方法区中的类元数据的指针(开启压缩指针时为4字节,否则8字节)

(3) 数组长度(可选,4字节)

如果是数组对象,额外存储数组长度

2. 实例数据(Instance Data)

存储对象真正的有效信息,即各个字段的内容,排列顺序受以下规则影响:

  1. 基本类型优先(long/double → int/float → short/char → byte/boolean)
  2. 相同宽度字段放在一起
  3. 父类字段在子类之前

字段内存占用

类型 大小
boolean 1字节
byte 1字节
short 2字节
char 2字节
int 4字节
float 4字节
long 8字节
double 8字节
引用类型 4字节(压缩指针)或8字节

示例:

class MyObject {
    byte b;      // 1字节
    int i;       // 4字节
    long l;      // 8字节
    Object ref;  // 4字节(压缩指针)
}
// 实例数据总大小 = 1 + 4 + 8 + 4 = 17字节

3. 对齐填充(Padding)

JVM要求对象起始地址必须是8字节的整数倍,因此可能需要填充字节(0-7字节)

示例计算

对象头:12字节 (MarkWord 8 + KlassPointer 4)
实例数据:17字节
总计:12 + 17 = 29字节
需要填充到32字节(8的倍数)
最终对象大小:32字节

4. 完整对象内存布局示例

[对象头]
  [Mark Word(8字节)] 0x00000001d83eb950
  [Klass Pointer(4字节)] 0x0000000100000000
  [数组长度(4字节)] 0x00000005 (仅数组对象有)
[实例数据]
  [int id(4字节)] 0x00000001
  [String name(4字节)] 0x000000076bdc8c18
  [double price(8字节)] 0x4024000000000000
[对齐填充(4字节)] 0x00000000

5. 查看对象内存布局的方法

(1) 使用JOL工具

// 添加依赖
<dependency>
    <groupId>org.openjdk.jol</groupId>
    <artifactId>jol-core</artifactId>
    <version>0.16</version>
</dependency>

// 打印对象布局
System.out.println(ClassLayout.parseInstance(obj).toPrintable());

(2) 示例输出

class com.example.MyObject object internals:
OFF  SZ               TYPE DESCRIPTION               VALUE
  0   8                    (object header: mark)     0x00000001d83eb950
  8   4                    (object header: class)    0x0000000100000000
 12   4                int MyObject.id               1
 16   8             double MyObject.price            10.0
 24   4   java.lang.String MyObject.name             "test"
 28   4                    (object alignment gap)    
Instance size: 32 bytes

6. 对象结构优化技巧

  1. 字段重排序:手动排列字段可减少填充

    // 优化前:需要4字节填充
    class Bad {
        byte b;
        long l;
        int i;
    }
    // 优化后:无填充
    class Good {
        long l;
        int i;
        byte b;
    }
    
  2. 使用基本类型:避免包装类(Integer等)的内存开销

  3. 对象共享:对于不变对象可复用(如String池)

资料免费获取