标记-清除算法
效率不高,而且存在内存碎片的问题。复制算法
标记-整理算法
分代收集算法
- 新建的对象优先分配在Eden区;
- 当Eden区满了,就会触发Minor GC,Eden中的存活对象被移动到Survivor0,Eden被清空;
- 等Eden区再满了,再次触发Minor GC,Eden和Survivor0中的存活对象又会被复制到Survivor1,S0和Eden被清空,然后下一轮S0与S1交换角色,如此循环往复。
- 当两个Survivor区切换了几次(HotSpot虚拟机默认15次)之后,仍然存活的对象,将被复制到老年代。
Minor GC:发生在新生代的GC,因为Java对象都具备朝生夕灭的特性,所以Minor GC非常频繁,一般回收速度也比较快。
Major GC/Full GC:发生在老年代年的GC,出现Full GC经常伴随至少一次的Minor GC(非绝对,如Parallel Scavenge)。Full GC的速度一般会比Minor GC慢10倍以上,所以要合理设置年轻代与老年代的大小,尽量减少Full GC的操作。
- 当Eden区满时触发。
- 调用System.gc时,系统会建议执行Full GC,但是不一定执行。
- 老年代空间不足时触发。
- 方法区(永久代/元空间)空间不足时触发。
- 通过Minor GC后进入老年代的平均大小大于老年代的可用连续内存时触发。
- 由Eden区、From Space区向To Space区复制时,对象大小大于To Space可用内存,则把该对象转存到老年代,且老年代的可用连续内存小于该对象大小时触发。
对象优先在Eden区分配
一次Minor GC。大对象直接进入老年代
长期存活的对象将进入老年代
动态对象年龄判定
空间分配担保
- Serial:单线程的收集器。==复制算法==
- ParNew:Serial 收集器的多线程版本。==复制算法==
- Parallel Scavenge:类似ParNew的收集器,其他收集器关注于尽可能缩短 Stop The World 的时间, 而Parallel 收集器更关注系统的吞吐量,支持自适应调节策略。==复制算法==
- Serial Old:Serial 收集器的老年代版本。==标记整理算法==
- Parallel Old:Parallel Scavenge 收集器的老年代版本。==标记整理算法==
- CMS:Concurrent Mark Sweep 收集器是一种以获取最短回收停顿时间为目标的收集器。==标记清除算法==
- 初始标记(Initial Mark):标记出老年代里面存活的对象,这些对象或者是从GC roots直接指向的,或者是被年轻代存活对象指向的。会导致 STW,速度最快。
- 并发标记(Concurrent Mark):从上个阶段找到的所有根节点开始遍历整个老年代,标记存活的对象。速度慢,但是是和程序并发执行的。
- 重新标记(Final Remark):由于之前的并发标记是并发过程,可能无法赶上应用程序的修改速度。所以需要重新标记来完成标记整个老生代存活对象的标记。会导致 STW,速度快。
- 并发清除(Concurrent Sweep):并发清除死亡的对象。速度慢,但是是和程序并发执行的。
- 对CPU资源非常敏感。CMS默认回收线程数是(CPU数量+3)/4。
- 无法处理浮动垃圾,可能出现“Concurrent Mode Failure”失败而导致另一次Full GC的产生。CMS并发清理阶段用户线程还在运行,伴随程序运行自然有新的垃圾不断产生,这部分垃圾出现在标记过程之后,CMS无法在当次收集中处理掉它们,只好留到下次GC再清理。这部分垃圾就是浮动垃圾。因为垃圾收集阶段的用户线程还要运行,所以CMS不像其他收集器那样等老年代几乎填满了在收集,会预留一部分空间。-XX:CMSInitiatingOccupancyFraction可以设置触发的百分比。当预留的内存无法满足程序需要,就会出现出现“Concurrent Mode Failure”失败,此时,虚拟机启动后备方案:临时启用Serial Old。
- 标记-清除算法的缺陷。易产生内存碎片。解决方法:通过参数配置,用于CMS在Full GC 时开启内存碎片的合并整理过程,内存整理过程无法并发,会导致STW时间变长,因此有另一个参数配置,用于设置执行多少次不压缩的Full GC后,执行压缩会Full GC。
7.G1:面向服务端应用。
- 并发与并行:充分利用多CPU、多核环境的硬件优势,缩短STW。
- 分代收集:保留分代概念,能独立管理整个GC堆。
- 空间整理:基于“标记-整理“,局部(两个Region)上看基于“复制”算法。所以不会产生内存空间碎片。
- 可预知的停顿:这是G1相对于CMS的另一大优势,能让使用者明确指定一个长度为M毫秒的时间片段内,消耗在垃圾收集上的时间不得超过N毫秒。
- 初始标记(Initial Mark):类似CMS
- 并发标记(Concurrent Mark):类似CMS
- 最终标记(Remark):类似CMS
- 筛选回收(cleanp):在此阶段将对象从一个或多个区域复制到单一区域,同时整理和释放内存。
8.ZGC:JDK 11 引入的,号称具有更低延迟的垃圾收集器,利用有色指针、加载屏障等技术,将 STW 控制在一次,只做一次扫描就能实现垃圾收集。
参数 | 功能 |
---|---|
-XX:+UseConcMarkSweepGC | 自动启用-XX:+UseParNewGC |
-XX:+UseParallelGC | 自动启用-XX:+UseParallelOldGC。Server模式下的默认值。 |
-XX:+UseParallelOldGC | 自动启用-XX:+UseParallelGC |
-XX:+UseParNewGC | JDK8不能单独启用 |
-XX:+UseSerialGC | Serial + Serial Old。Client模式下的默认值。 |
-XX:+UseG1GC | 使用G1垃圾收集器 |
参考资料:《深入理解Java虚拟机(第二版)》、《Java虚拟机规范(Java SE 8版)》、GC Algorithms: Implementations