对象分配在哪块内存?
对象在JVM中的分配遵循分代分配策略,核心依据是对象的生命周期长短,具体分配位置如下:
1. 优先分配到年轻代的伊甸区(Eden Space)
这是对象分配的默认且最主要的位置。程序中所有新创建的对象(如 new Object()),都会优先被分配到年轻代的伊甸区。
这是因为JVM基于“大部分对象朝生夕死”的特性设计,伊甸区作为对象的“出生地”,能快速容纳新对象,后续通过Minor GC(年轻代GC)高效回收短命对象。
2. 大对象直接分配到老年代
对于体积过大的对象(如长度极长的数组、占用内存较多的集合),会直接跳过年轻代,分配到老年代。
-
目的:避免大对象在年轻代的伊甸区和幸存者区之间频繁复制(复制算法会产生大量开销),减少Minor GC的性能消耗。
-
阈值:大对象的判定标准由JVM参数 XX:PretenureSizeThreshold 控制(默认无明确值,不同JVM实现有差异)。
3. 长期存活的对象从年轻代晋升到老年代
年轻代中“存活较久”的对象,会逐步从年轻代晋升到老年代,具体逻辑:
-
对象在年轻代的幸存者区(Survivor 0/1)中,每经历一次Minor GC且存活,其“年龄计数器”会+1。
-
当年龄达到JVM阈值(默认15,由参数 XX:MaxTenuringThreshold 控制)时,对象会被“晋升”到老年代,成为长期存活对象。
4. 特殊情况:栈上分配与TLAB
• 栈上分配:对于“逃逸分析”判定为“不会逃出方法作用域”的对象(如方法内临时创建、仅在方法内使用的对象),会直接分配在当前线程的栈帧中,而非堆内存。栈帧销毁时对象自动回收,无需GC参与,性能极高。
• TLAB(线程本地分配缓冲):为避免多线程在伊甸区分配对象时的竞争,JVM会为每个线程在伊甸区划分一块“私有缓冲区域”(TLAB),线程创建对象时优先在自己的TLAB中分配,进一步提升分配效率。
总结
对象分配的核心流程
-
新对象优先分配到伊甸区(或线程的TLAB);
-
若为大对象,直接分配到老年代;
-
年轻代中存活的对象经多轮Minor GC后,年龄达标则晋升到老年代;
-
无逃逸的临时对象,直接分配到线程栈(非堆内存)。