目录
1 新生代垃圾收集器
1.1 Serial收集器
1.2 ParNew收集器
1.3 Parallel Scavenge收集器
2 老年代收集器
2.1 Serial Old收集器
2.2 Parallel Old收集器
2.3 CMS收集器
3 G1收集器
3.1 特点
3.2 过程
3.3 相关jvm参数
4 配置垃圾收集器类型
jvm垃圾收集器整体可以分为三大类,新生代垃圾收集器、老年代垃圾收集器、全局垃圾收集器
1 新生代垃圾收集器
1.1 Serial收集器
Serial(串行)垃圾收集器是最基本、发展历史最悠久的收集器,单线程收集,进行垃圾收集的时候会停止用户线程
1.2 ParNew收集器
ParNew垃圾收集器是Serial收集器的多线程版本,除了多线程外,其余的行为、特点和Serial收集器一样;
相关jvm参数:
"-XX:ParallelGCThreads":指定垃圾收集的线程数量,ParNew默认开启的收集线程与CPU的数量相同;
1.3 Parallel Scavenge收集器
Parallel Scavenge垃圾收集器因为与吞吐量关系密切,也称为吞吐量收集器(Throughput Collector)
相关jvm参数:
"-XX:MaxGCPauseMillis":控制最大垃圾收集停顿时间,大于0的毫秒数。MaxGCPauseMillis设置得稍小,停顿时间可能会缩短,但也可能会使得吞吐量下降,因为可能导致垃圾收集发生得更频繁;
"-XX:GCTimeRatio":设置垃圾收集时间占总时间的比率,0<n<100的整数,级吞吐量
"-XX:+UseAdptiveSizePolicy":开启这个参数后就不用手工指定一些细节参数,如 新生代的大小(-Xmn)、Eden与Survivor区的比例(-XX:SurvivorRation)、晋升老年代的对象年龄(-XX:PretenureSizeThreshold)等。
JVM会根据当前系统运行情况收集性能监控信息,动态调整这些参数,以提供最合适的停顿时间或最大的吞吐量。使用该参数的时候只需要设置好堆内存大小,然后使用"-XX:MaxGCPauseMillis"或"-XX:GCTimeRatio"给JVM设置一个优化目标,优化细节jvm就可以自动完成。
2 老年代收集器
2.1 Serial Old收集器
是 Serial收集器的老年代版本
2.2 Parallel Old收集器
Parallel Old垃圾收集器是Parallel Scavenge收集器的老年代版本;
2.3 CMS收集器
第一次实现了让垃圾收集线程与用户线程同时工作。CMS垃圾收集过程分为4步
- 初始标记:标记一下GC Roots能直接关联到的对象(老年代中所有的GC Roots对象和年轻代中活着的对象引用到的老年代的对象),速度快,需停顿
- 并发标记:GC Root递归追踪
- 重新标记:修正在并发标记期间因用户继续运行而导致标记产生变动,速度稍慢,需停顿
- 并发清除:清除GC Root不可达对象,不需要停顿
优点:并发收集、低停顿。
缺点:
1)CMS收集器对CPU资源非常敏感。虽然在两个并发阶段不会导致用户线程停顿,但是会因为占用了一部分线程而导致应用程序变慢,总吞吐量下降。CMS默认启动的回收线程数是(CPU数量+3)/4。
2)CMS收集器无法处理浮动垃圾(在并发清除时,用户线程新产生的垃圾),可能出现“Conturrent Mode Failure”失败而导致另一次Full GC产生(Serail Old)。因此CMS收集器不能像其他收集器那样等待老年代填满之后再进行收集,需要预留一部分空间给并发收集时用户程序使用。可以通过"-XX:CMSInitiatingOccupancyFraction"(默认值92)参数设置老年代内存使用达到多少时启动收集。
3)会产生大量碎片。CMS收集器提供了一个"-XX:UseCMSCompactAtFullCollection"参数(默认是开启的)用于在CMS收集器顶不住要FullGC时开启内存碎片整理(需要停顿用户线程)。参数"-XX:CMSFullGCsBeforeCompaction"来设置执行多少次不压缩的Full GC后,跟着来一次带压缩的(默认值是0,意味着每次进入Full GC时都进行碎片整理)。
3 G1收集器
3.1 特点
G1充分利用多核,多CPU硬件优势,尽量缩短SWT
G1整体采用标记整理算法,局部(两个region)采用复制算法,不会产生内存碎片
宏观上G1不再区分新生代,老年代,把内存划分为多个独立的区域
G1收集器收集过程和CMS类似
3.2 过程
初始标记:标记一下GC Roots能直接关联到的对象(老年代中所有的GC Roots对象和年轻代中活着的对象引用到的老年代的对象),速度快,需停顿
并发标记:GC Root递归追踪
重新标记:修正在并发标记期间因用户继续运行而导致标记产生变动,速度稍慢,需停顿
筛选回收:首先排序各个Region的回收价值和成本, 然后根据用户期望的GC停顿时间来制定回收计划,最后按计划回收一些价值高的Region中垃圾对象
3.3 相关jvm参数
-XX:G1HeapRegionSize=n:设置的 G1 区域的大小。值是 2 的幂,范围是 1 MB 到 32 MB 之间
-XX:MaxGCPauseMillis=200:允许的GC最大的暂停时间。G1尽量确保每次GC暂停的时间都在设置的MaxGCPauseMillis范围内。
-XX:ParallelGCThreads=n:设置 STW 工作线程数的值。将 n 的值设置为逻辑处理器的数量。n 的值与逻辑处理器的数量相同,最多为 8
-XX:ConcGCThreads=n:设置并行标记的线程数。将n设置为并行垃圾回收线程数 (ParallelGCThreads) 的 1/4 左右。
-XX:InitiatingHeapOccupancyPercent: =45:设置触发标记周期的 Java 堆占用率阈值。默认占用率是整个 Java 堆的 45%。
4 配置垃圾收集器类型
-XX:+UseSerialGC:开启后会使用Serial(Yang区)和Serial Old(Old区)组合。新生代用复制算法,老年代用标记-整理算法
-XX:+UseSerialOldGC(已废弃)
-XX:+UseParallelGC/-XX:+UseParallelOldGC:开启后会使用Parallel Scavenge(Yang区)和Parallel Old(Old区)组合。新生代用复制算法,老年代用标记-整理算法。
-XX:+UseParNewGC:开启后会使用ParNew(Yang区)和Serial Old(Old区)组合。新生代用复制算法,老年代用标记-整理算法。
-XX:+UseConcMarkSweepGC:开启后会使用ParNew(Yang区)和CMS Old(Old区)组合。Serial Old将作为CMS Old出错的后备处理。新生代用复制算法,老年代用标记-清除算法。
-XX:+UseG1GC:开启G1全局收集器