Java对象内存分配主要在堆中进行,涉及类加载、TLAB分配、Eden区分配、Minor GC等步骤,布局包括对象头、实例数据和对齐填充,TLAB与指针压缩优化多线程分配效率与内存占用。

Java对象的内存分配主要发生在堆(Heap)中,由JVM在运行时动态完成。对象创建时,JVM会根据类信息、字段布局和运行时状态决定如何分配空间,整个过程涉及类加载、内存布局、指针压缩、TLAB(线程本地分配缓冲区)等多个环节。
对象内存分配的核心区域:堆
绝大多数对象实例都在堆中分配内存。堆是所有线程共享的运行时内存区域,由垃圾收集器统一管理。JVM启动时通过-Xms和-Xmx参数设定初始和最大堆大小。
- 新生代(Young Gen)占堆的大部分,新对象优先在此分配
- 大对象(如长数组)可能直接进入老年代(Old Gen),避免频繁复制
- 如果堆空间不足且无法扩展,会触发OutOfMemoryError: Java heap space
对象分配的关键步骤:从new到内存地址
执行new MyClass()时,JVM内部按以下顺序处理:
- 检查类是否已加载、解析、初始化;未完成则先触发类加载机制
- 计算对象所需内存大小(含对象头、实例字段、对齐填充)
- 尝试在TLAB中分配:每个线程独有小块内存,无锁快速分配
- TLAB不足时,再尝试在Eden区共享空间分配;失败则触发Minor GC
- 分配成功后,初始化对象头(Mark Word、Klass Pointer)、清零实例数据、调用构造方法
对象内存布局:三部分组成
一个Java对象在堆中的存储结构包含:
立即学习“Java免费学习笔记(深入)”;
- 对象头(Header):8字节(64位JVM开启指针压缩)或12字节(未开启),含哈希码、GC分代年龄、锁状态、指向类元数据的指针
- 实例数据(Instance Data):字段按宽度排序(long/double → int → short/char → byte/boolean),父类字段在前,子类在后
- 对齐填充(Padding):保证对象总长度为8字节整数倍,便于CPU高速缓存访问
影响分配行为的重要机制:TLAB与指针压缩
TLAB和压缩Oops(Ordinary Object Pointers)显著优化了多线程下的分配效率和内存占用。
- TLAB默认开启(-XX:+UseTLAB),减少Eden区同步竞争;可通过-XX:TLABSize调整大小
- 64位JVM默认启用指针压缩(-XX:+UseCompressedOops),将Klass Pointer等从8字节压缩为4字节,节省堆内存
- 当堆超过32GB(理论阈值)时,压缩指针失效,对象头变大,间接增加内存开销










