截止JDK1.8,主要的垃圾收集器如下所示:
注1:浮动垃圾,当次回收无法清除的垃圾,产生于用户线程与GC线程并发执行
名称 | 使用区域 | 缺点 | 优点 | 版本 | 算法 |
Serial | 新生代 | 单线程收集,导致Stop the World | 简单、高效,无线程交互开销 | 1.3.1前 | 复制 |
ParNew | 新生代 | 导致Stop the World,单CPU下因为线程交互效果反而若于Serial | 多线程收集,简单,可与CMS收集器配合工作 | 复制 | |
Parallel Scavenge | 新生代 | 可控制吞吐量(用户代码运行时间/JVM运行总时间) | 1.4 | 复制 | |
Serial Old | 老年代 | 单线程收集,导致Stop the World | 简单、高效,无线程交互开销,可以搭配Parallel Scavenge使用,可以作为CMS收集器后备方案 | 1.5前 | 标记-整理 |
Parallel Old | 老年代 | 注重吞吐量 | 1.6发布 | 标记-整理 | |
CMS | 老年代 | 对CPU资源敏感,回收过程可能导致系统变慢,无法处理浮动垃圾(注1),因为标记-清除算法缺点导致出现大量内存碎片,在分配大对象时出发Full GC | 系统停顿时间短,并发收集 | 1.5发布 | 标记-清除 |
G1 | 全部 | 截止JDK1.7尚无生产环境性能报告 | 支持并发、并行,停顿时间短,可以管理整个内存堆,可以整合空间,避免出现内存碎片,可以预测停顿时间 | 1.6开始实验,1.7正式发布 | 整体是标记-整理,Region之间是复制 |
相关JVM设置如表所示:
注2: 内存分配担保机制:就是当在新生代无法分配内存的时候,把新生代的对象转移到老生代,然后把新对象放入腾空的新生代。
参数 | 描述 |
UseSerialGC | 虚拟机运行在client 模式下的默认值,打开此开关使用Serial + Serial Old收集器组合进行垃圾回收 |
UseParNewGc | 打开此开关使用使用ParNew + Serial Old收集器组合进行垃圾回收 |
UseConcMarkSweepGC | 打开此开关使用使用ParNew + CMS + Serial Old收集器组合进行垃圾回收。Serial Old将作为CMS回收失败的后备收集器使用 |
UseParallelGC | 虚拟机运行在server 模式下的默认值,打开此开关使用Parallel Scavenge + Serial Old收集器组合进行垃圾回收 |
useParallelOldGC | 打开此开关使用使用Parallel Scavenge + Parallel Old收集器组合进行垃圾回收 |
SurvivorRatio | 新生代Eden区域和Survivor区域的大小比值,默认为8:1 |
PretenureSizeThreshold | 直接晋升到老年代的对象大小,设置以后大于这个值的对象直接分配在老年代 |
MaxTenuringThreshold | 直接晋升到老年代的对象年龄,每个对象在坚持过一次Minor GC后,年龄+1,年龄大于这个值的直接进入老年代 |
UseAdaptiveSizePolicy | 动态调整Java堆中各个区域的大小以及进入老年代的年龄 |
HandlePromotionFailure | 是否允许分配担保失败(注2),即老年代剩余空间不足以应对新生代整个区域存活的极端情况 |
ParallelGCThreads | 设置并行GC时内存回收的线程数 |
GCTimeRatio | GC时间占总时间的比率,默认值99,即允许GC时间为1%,仅在Parallel Scavenge收集器生效 |
MaxGCPauseMillis | 设置GC最大停顿时间,尽在Parallel Scavenge收集器生效 |
CMSInitiatingOccupancyFraction | 设置CMS收集器在老年代空间被使用多少后出发GC,默认68%,仅在CMS收集器生效 |
UseCMSCompactAtFullCollection | 设置CMS收集器在完成垃圾回收后是否进行内存碎片整理,仅在CMS收集器生效 |
CMSFullGCsBeforeCompaction | 设置CMS收集器在进行若干次垃圾回收后再进行内存碎片整理,仅在CMS收集器生效 |