在Java虚拟机(JVM)中,垃圾回收(Garbage Collection, GC)是自动内存管理的核心机制,负责回收不再使用的对象以释放内存。以下是几种垃圾回收器的原理及优缺点:
1.标记清除法:
原理:对堆内存中各个存活对象进行标记,然后清除未被标记的对象。
缺点:1.因为垃圾并不一定存在于连续的内存空间,所以会导致内存碎片化;
2.效率较低:需要两次遍历内存(标记+清除)
使用场景:老年代
2.复制清除法:
原理:先将存活对象进行复制到一个统一的内存区(从from到to),然后将from区统一清除。
优点:无内存碎片。
缺点:1.需要额外的空间;
2.不适用于存活对象较多的场景。
适用场景:新生代(对象存活率较低)
3.标记整理法:
原理:将存活对象在内存上移动到一起,然后统一进行再进行清除。
优点:无内存碎片化。
缺点:移动对象需要花费额外的资源,且效率较低。
4.分代收集算法:
原理:是最常用的算法,根据对象存存活周期,将堆内存分为新生代和老年代,在新生代中 应用复制算法(Eden+Survivor)、在老年代中应用标记清除算法+标记整理算法。
在进行垃圾回收(GC)的时候,在新生代进行复制清除算法,将Eden区的存活对象复制到Survivor区,而Survivor区又分为几个大小相等的s0、s1、s2区(也可理解为from survivor区和to survivor区),首先会将存活对象移动到s0区,然后清除Eden区,在Survivor区中同样进行复制算法,比如(Eden+s0->s1),对象年龄+1,最终经历过14次(或达到阈值-XX:MaxTenuringThreshold=15)GC仍未被回收的对象将被视为长期存活对象,会被放入老年代,而对象本身较大(大于1/2老年代空间的对象会直接被放入老年代,或通过 -XX:PretenureSizeThreshold
设置阈值),在老年代中基本不进行垃圾回收(仅在发生FullGC的时候进行垃圾回收)。
优点:将存活周期长的对象和存活周期短的对象分开存储,减少了内存扫描次数和范围
原理图:
对象分配 → Eden区↓
Eden满 → Minor GC↓
存活对象复制到 Survivor区(年龄+1)↓
年龄 ≥ 阈值 或 Survivor不足 → 晋升到老年代↓
老年代空间不足 → 触发 Full GC