标记-清除算法(Mark and Sweep)
- 标记:从根集合进行扫描,对存活的对象进行标记;
- 清除:对堆内存从头到尾进行线性遍历,回收不可达对象内存;
它是最基础的算法,存在两个不足:1、效率问题,标记和清除效率都不高;2、空间问题,标记-清除后,会产生不连续的内存碎片;
复制算法:
- 分为对象面和空闲面
- 对象在对象面上创建
- 存活的对象被从对象面复制到空闲面
- 将对象面所有对象内存清除
它解决了碎片化问题、顺序分配内存,简单高效、适用于对象存活率低的场景;
标记-整理算法:
- 标记:从根集合进行扫描,对存活对象进行标记;
- 整理:移动所有存活的对象,且按照内存地址次序一次排序,然后将末端内存地址以后的内存全部回收;
它避免了内存的不连续性、不用设置两块内存互换、适用于存活率高的场景;
分代收集算法:
GC的分类:Minor GC、Full GC
年轻代:
尽可能快速地收集掉那些生命周期短的对象,是由Eden区和两个Survivor区组成(8:1:1);
对象在年轻代经历过多次GC后进入老年代的次数参数设置:-XX:MaxTenuringThreshold
对象如何晋升到老年代:
- 经历一定Minor 次数依然存活的对象;
- Survivor区中存放不下的对象;
- 新生成的大对象(-XX:+PretenuerSizeThreshold)
常用的调优参数:
- -XX:SurvivorRatio:Eden和Survivor的比值,默认:8:1
- -XX:NewRatio:老年代和年轻代内存大小的比例
- -XX:MaxTenuringThreshold:对象从年轻代晋升到老年代经过GC次数的最大阈值
触发Full GC的条件:
- 老年代空间不足
- 永久代空间不足
- CMS GC时出现promotion failed,concurrent mode failure
- Minor GC晋升到老年代的平均大小大于老年代的剩余空间
- 调用System.gc()
- 使用RMI来进行RPC或管理的JDK应用,每小时执行1次Full GC