经典垃圾收集器
经典垃圾收集器包含:
- 新生代收集器:Serial收集器,ParNew收集器, Parallel Scavenge收集器
- 老年代收集器:Serial Old收集器,Parallel Old收集器,CMS收集器
- 全堆收集器:G1收集器
目录
一、Serial收集器
- 新生代收集器,基于标记-复制算法实现
- 单线程工作收集器。这里的单线程指它在进行垃圾收集时,必须暂停其他所有工作线程,直至它收集结束。
- 简单而高效,对于内存资源受限的环境,Serial收集器额外内存消耗是最小的。
- 对于单核处理器或处理器核心数较少的环境,Serial收集器可以获得最高的单线程收集效率。
- Serial收集器适合运行在客户端模式下的虚拟机
控制参数:
- -XX:SurvivorRatio:Eden与Survivor区的比例
- -XX:PretenureSizeThreshold:晋升老年代对象大小
- -XX:HandlePromotionFailure:是否设置空间分配担保,JDK7及以后失效
二、ParNew收集器
- 新生代收集器,基于标记-复制算法实现
- Serial收集器的多线程并行版本。
- 除了Serial收集器外,只有ParNew收集器能与CMS收集器配合使用
- ParNew收集器是激活CMS后的默认新生代收集器
- 在单核心处理器的环境中效果没有Serial收集器好,因为存在线程交互的开销
- 在多核心处理器的环境中,默认开启的收集线程数与处理器核心数相同,可使用-XX:ParallelGCThreads限制垃圾收集的线程数
控制参数:
- -XX:+UseConcMarkSweepGC:使用CMS收集器
- -XX:+/-UseParNewGC:指定收集器为ParNew收集器或者禁用它
- -XX:ParallelGCThreads:限制垃圾收集的线程数
三、Parallel Scavenge收集器
- 新生代收集器,基于标记-复制算法实现
- 并行收集的多线程收集器
- Parallel Scavenge收集器的目标是达到一个可控制的吞吐量,即缩短运行垃圾收集的时间
控制参数:
- -XX:MaxGCPauseMillis:控制最大垃圾收集停顿时间
- -XX:GCTimeRatio:直接设置吞吐量大小
- -XX:+UseAdaptiveSizePolicy:开启垃圾收集器的自适应调节策略
四、Serial Old收集器
- 老年代收集器,基于标记-整理算法实现
- 单线程收集器
- JDK5之前与Parallel Scavenge收集器搭配使用
- 作为CMS收集器失败时,并发收集发生Concurrent Mode Failure时使用
五、Parallel Old收集器
- 老年代收集器,基于标记-整理算法实现
- 多线程收集器
- 在注重吞吐量或者处理器资源较为稀缺的场合,可以优先考虑使用Parallel Scavenge+Parallel Old
六、CMS收集器
- 老年代收集器,基于标记-清除算法实现
- 第一款支持并发的垃圾收集器
- CMS(Concurrent Mark Sweep)收集器是以获取最短回收停顿时间为目标的收集器
- JDK9后被生命为不推荐使用
过程:
- 初识标记(CMS initial mark)
- 并发标记(CMS concurrent mark)
- 重新标记(CMS remark)
- 并发清除(CMS concurrent sweep)
初始标记速度很快,需要做用户停顿;并发标记速度较慢,不需要做用户停顿,可与用户线程并发运行;重新标记速度比初始标记稍慢,需要做用户停顿;并发清除耗时较长,不需要做用户停顿,可与用户线程并发运行。
优点:
- 并发收集
- 低停顿
缺点:
- 对处理器资源非常敏感
- 无法处理“浮动垃圾”,可能出现“Concurrent Mode Failure”失败导致一次完全的“Stop The World”的Full GC产生。
- 由于急于“标记-清除”算法,会产生大量的空间碎片
控制参数:
- -XX:CMSInitiatingOccu-pancyFraction:CMS启动阈值
- -XX:UseCMSCompactAtFullCollection:开启内存碎片合并整理过程
- -XX:CMSFullGCsBeforeCompaction:执行不整理空间的Full GC的次数
七、Garbage First收集器
- 面向局部收集的设计思路与基于Region内存布局形式
- G1收集器是一个面向全堆的收集器,不需要其他新生代收集器的配合工作
- G1收集器可以面向堆内存任何部分来组成回收集进行回收,不再以哪个分代进行回收,而是以回收哪块内存区域的收益最大来进行回收
- JDK9后取代了Parallel Scavenge+Parallel Old,成为了服务端模式下的默认垃圾收集器
- G1中的新生代与老年代不是固定的,而是一系列区域(不一定是连续)的动态集合
G1收集器需解决的问题:
- 将Java堆分成多个独立的Region后,Region里面存在的跨Region引用对象如何解决?
- 在并发标记阶段如何保证收集线程与用户线程互不干扰地运行?
- 怎样建立可靠的停顿预测模型?
过程:
- 初始标记
- 并发标记
- 最终标记
- 筛选回收
除了并发标记不需要暂停用户线程,其余都是要暂停用户线程的。
G1与CMS对比:
G1 | CMS | |
---|---|---|
内存空间碎片 | 不会产生 | 会产生 |
内存占用 | 比CMS高 | * |
执行负载 | 比CMS高 | * |
小内存应用 | 性能劣于CMS | * |
大内存应用 | 性能优于CMS | * |
控制参数:
- -XX:G1HeapRegionSize:每个Region的大小,范围为1MB-32MB,应为2的N次幂
- -XX:MaxGCPauseMills:允许的收集停顿时间