堆内存布局
新生代
新生代用于存放新创建的对象;
它分为三个部分:Eden区、Survivor区(通常有两个,称为From和To);
大多数对象首先在Eden区分配,经过一次Minor GC后,存活的对象会被移到Survivor区,经过多次GC后仍然存活的对象会被晋升到老年代。
老年代
老年代用于存放长期存活的对象;
当对象在新生代经过多次GC后仍然存活,会被移到老年代;
老年代的GC频率较低,通常使用Major GC或Full GC进行垃圾回收。
Eden区和Survivor区的功能
Eden区
功能:存放新创建的对象;
特点
大多数对象在Eden区创建;
Eden区通常占新生代的较大比例(默认约为80%);
当Eden区满时,会触发Minor GC(新生代垃圾回收)。
Survivor区
功能:存放经过Minor GC后仍然存活的对象;
特点
Survivor区分为From和To两个区域,每次Minor GC时交替使用;
对象在Survivor区之间复制,直到达到一定年龄(默认15岁)后晋升到老年代;
Survivor区的存在是为了减少直接晋升到老年代的对象数量,从而降低老年代的压力。
新生代垃圾回收的过程
新生代的垃圾回收(Minor GC)通常采用复制算法,具体过程如下:
对象分配
新创建的对象首先分配在Eden区。
Minor GC触发
当Eden区满时,触发Minor GC。
标记存活对象
垃圾回收器会标记Eden区和From Survivor区中所有存活的对象。
复制存活对象
将Eden区和From Survivor区中的存活对象复制到To Survivor区;
如果对象的年龄达到一定阈值(默认15岁),则直接晋升到老年代。
清空Eden区和From Survivor区
复制完成后,清空Eden区和From Survivor区。
交换Survivor区
将From Survivor区和To Survivor区的角色互换,以便下次Minor GC时使用。
Survivor区的设计目的
减少直接晋升到老年代的对象数量
通过Survivor区的多次复制,只有长期存活的对象才会晋升到老年代;
这样可以减少老年代的压力,避免频繁触发Full GC。
优化垃圾回收效率
复制算法只需要复制存活对象,而不需要处理死亡对象,因此效率较高;
Survivor区的存在使得复制算法的开销更小。
提高内存利用率
Survivor区的设计使得新生代的内存空间得到更高效的利用;
通过多次Minor GC,可以筛选出真正需要长期存活的对象。
相关JVM参数
-XX:NewRatio
:设置新生代与老年代的比例;-XX:SurvivorRatio
:设置Eden区与Survivor区的比例;-XX:MaxTenuringThreshold
:设置对象晋升到老年代的年龄阈值。