Serial和Serial Old垃圾回收器
分别用来回收新生代和老年代的垃圾对象
工作原理就是单线程运行,垃圾回收的时候会停止我们自己写的系统的其他工作线程,让我们系统直接卡死不动,然后让他们垃圾回收,这个现在一般写后台Java系统几乎不用。
ParNew
ParNew现在一般都是用在新生代的垃圾回收器。
-XX:+UseParNewGC 新生代使用ParNew。
ParNew垃圾回收器如果一旦在合适的时机执行Minor GC的时候,就会把系统程序的工作线程全部停 掉,禁止程序继续运行创建新的对象,然后自己就用多个垃圾回收线程去进行垃圾回收。
默认线程数取决于机器cpu核数.如果要调节,使用-XX:ParallelGCThreads。
Parallel Scavenge
新生代并发,复制算法
可以达到一个可控制的吞吐量
-XX:MaxGCPauseMillis :控制最大的垃圾收集停顿时间(尽力)
-XX:GCTimeRatioi:设置吞吐量的大小,取值0-100,系统花费不超过1/(1 +n)的时间用于垃圾收集
自适应GC策略:可用-XX:+ UseAdptiveSizePolicy打开
打开自适应策略后,无需手动设置新生代的大小( -Xmn )、Eden与Survivor区的比例( -XX:SurvivorRatio )等参数虚拟机会自动根据系统的运行状况收集性能监控信息,动态地调整这些参数,从而达到最优的停顿时间以及最高的吞吐量
CMS
CMS采取的“标记-清理”算法。
CMS在执行一次垃圾回收的过程一共分为4个阶段:
初始标记(STW)
并发标记
重新标记(STW)
并发清理
CMS默认启动的垃圾回收线程的数量是(CPU核数 + 3)/ 4。
-XX:CMSInitiatingOccupancyFaction 参数可以用来设置老年代占用多少比例的时候触发CMS垃圾回收,默认68%。
老年代占用了92%空间了,就自动进行CMS垃圾回收,预留8%的空间给并发回收期间,系统程序把一些新对象放入老年代中。
如果CMS垃圾回收期间,系统程序要放入老年代的对象大于了可用内存空间。会发生Concurrent Mode Failure。就会自动用“Serial Old”垃圾回收器替代CMS,就是直接强行把系统程序“Stop the World”,重新进行长时间的GC Roots追踪,标记出来全部垃圾对象,不允许新的对象产生。
在生产实践中,这个自动触发CMS垃圾回收的比例需要合理优化一下,避免“Concurrent Mode Failure”问题
-XX:+UseCMSCompactAtFullCollection默认是打开的,在Full GC之后要再次进行“Stop the World”,停止工作线程,然后进行碎片整理,就是把存活对象挪到一起,空出来大片连续内存空间,避免内存碎片。
-XX:CMSFullGCsBeforeCompaction,这个意思是执行多少次Full GC之后再执行一次内存碎片整理的工作,默认是0,意思就是每次Full GC之后都会进行一次内存整理。
-XX:+CMSParallelInitialMarkEnabled,这个参数会在CMS垃圾回收器的“初始标记”阶段开启多线程并发执行。
-XX:+CMSScavengeBeforeRemark,这个参数会在CMS的重新标记阶段之前,先尽量执行一次Young GC。
G1
把Java堆内存拆分为多个大小相等的Region。
G1也会有新生代和老年代的概念,但是只不过是逻辑上的概念。
G1最大的一个特点,就是可以让我们设置一个垃圾回收的预期停顿时间。
G1可以做到让你来设定垃圾回收对系统的影响,他自己通过把内存拆分为大量小Region,以及追踪每个Region中可以 回收的对象大小和预估时间,最后在垃圾回收的时候,尽量把垃圾回收对系统造成的影响控制在你指定的时间范围内,同时在有限的时 间内尽量回收尽可能多的垃圾对象
-XX:+UseG1GC,会自动用堆大小除以2048,因为JVM最多可以有2048个Region,然后Region的大小必须是2的倍数
如果通过手动方式来指定,则是-XX:G1HeapRegionSize
刚开始的时候,默认新生代对堆内存的占比是5%,也就是占据200MB左右的内存,对应大概是100个Region,这个是可以通过“- XX:G1NewSizePercent”来设置新生代初始占比的,其实维持这个默认值即可。
因为在系统运行中,JVM其实会不停的给新生代增加更多的Region,但是最多新生代的占比不会超过60%,可以通过“- XX:G1MaxNewSizePercent”。
根据你预设的gc停顿时间,给新生代分配一些 Region,然后到一定程度就触发gc,并且把gc时间控制在预设范围内,尽量避免一次性回收过多的Region导致gc停 顿时间超出预期。
G1执行GC的时候最多可以让系统停顿多长时间,可 以通过“-XX:MaxGCPauseMills”参数来设定,默认值是200ms。
G1提供了专门的Region来存放大对象,而不是让大对象进入老年代的Region中
在G1中,大对象的判定规则就是一个大对象超过了一个Region大小的50%
其实新生代、老年代在回收的时候,会顺带带着大对象Region一起回收,所以这就是在G1内存模型下对大对象的分配和回收的策略。
G1有一个参数,是“-XX:InitiatingHeapOccupancyPercent”,他的默认值是45%。意思就是说,如果老年代占据了堆内存的45%的Region的时候,此时就会尝试触发一个新生代+老年代一起回收的混合回收阶段。
“-XX:G1MixedGCCountTarget”参数,就是在一次混合回收的过程中,最后一个阶段执行几次混合回收,默认值是8次
意味着最后一个阶段,先停止系统运行,混合回收一些Region,再恢复系统运行,接着再次禁止系统运行,混合回收一些Region,反 复8次。
“-XX:G1HeapWastePercent”,默认值是5%。在混合回收的时候,对Region回收都是基于复制算法进行的,都是把要回收的Region里的存活对象放入其他 Region,然后这个Region中的垃圾对象全部清理掉。在回收过程就会不断空出来新的Region,一旦空闲出来的Region数量达到了堆内存的5%,此时就会 立即停止混合回收。
“-XX:G1MixedGCLiveThresholdPercent”,他的默认值是85%,意思就是确定要回收的Region的时候,必须是存 活对象低于85%的Region才可以进行回收
如果在进行Mixed回收的时候,无论是年轻代还是老年代都基于复制算法进行回收,都要把各个Region的存活对象拷贝到别的Region 里去。一旦失败,立马就会切换为停止系统程序,然后采用单线程进行标记、清理和压缩整理,空闲出来一批Region,这个过程是极慢极慢 的。
评论区