对回收算法落地,出现了多种垃圾回收器:
搭配有:
图中虚线为对应版本的废弃组合。
Serial:
Serial Old:
添加JVM参数:
-XX:+UseSerialGC
新生代、老年代即使用Serial + Serial Old回收器组合。
添加JVM参数:
-XX:+UseParNewGC
此参数对应的组合是:ParNew + Serial Old(已过时的组合)
CMS步骤:
整个过程,有两个步骤需要STW,而这两步又耗时最短,因此,CMS的SWT短
CMS的缺点:
//调整多少次Full GC后进行整理
-XX:CMSFullGCsBeforeCompaction=N 参数(默认0)
基于以上缺点,JDK14后废弃CMS。添加JVM参数:
-XX:+UseParNewGC -XX:+UseConcMarkSweepGC
新老两块的回收器搭配就是ParNew + CMS
Parallel Scavenge:
Parallel Old:
添加如下JVM参数,可以使用Parallel Scavenge + Parallel Old组合:
-XX:+UseParallelGC 或
-XX:+UseParallelOldGC
最大暂停时间参数:
//毫秒
-XX:MaxGCPauseMillis=n
吞吐的设置:
-XX:GCTimeRatio=n
//吞吐为n,则用户线程执行时间 = n/n + 1,n=99,则99%的时间执行用户代码
开启自动调整内存大小(默认):
//JVM根据吞吐和STW最大时间自动调整堆大小
-XX:+UseAdaptiveSizePolicy
注意最大时间和吞吐两项是矛盾的,最大暂停时间极小,吞吐量又设置很大,后者可能得不到保证。添加如下JVM参数,程序启动的时候,打印所有配置项的值:
-XX:+PrintFlagsFinal
指定使用PS+PO组合,看下他们的默认配置:发现默认吞吐为99,即用户线程执行99%的时间,执行GC时间占1%,最大暂停时间则很大,相当于没有设置
PS:
//终端执行以下指令,打印默认参数配置项
java -XX:+PrintCommandLineFlags -version
关于G1:
优点:
缺点:
G1前,堆内存的划分是连续的
G1下,堆被分为一块块大小相等的区Region:
-XX:G1HeapRegionSize=32m
可设置每块的大小,但值必须为2次幂,且在1~32之间(2、4、8、16、32)使用G1需要添加JVM参数(JDK9及以后版本不用):
-XX:+UseG1GC
设置最大暂停时间:
-XX:MaxGCPauseMillis=毫秒值
? 这个选择一部分区域的实现思路是:G1下的Young GC,会记录回收每个区Region(Eden和幸存者区)的平均耗时,做为下次回收的依据,默认-XX:MaxGCPauseMillis=200,如果计算每块Region平均耗时为40ms,则每次触发Young GC时,就最多干掉四块
//阈值默认45%,可改
-XX:InitiatingHeapOccupancyPercent默认45%
注意和CMS的区别,流程像,但干的活儿不一样,且最后清理时,采用的算法也不一样。此外,G1对老年代的清理会选择存活度最低的区域来进行回收,以保证回收效率。
最后,因为清理是复制算法,如果清理时发现没有空Region去存放转移的对象(没地儿复制了),则转为单线程执行标记-整理算法进行Full GC,此时会导致用户线程的暂停。
JDK8及之前:
JDK9及以后: