侧边栏壁纸
  • 累计撰写 43 篇文章
  • 累计创建 9 个标签
  • 累计收到 0 条评论

目 录CONTENT

文章目录

JVM的各GC回收器原理及参数

landonchan
2015-12-18 / 0 评论 / 0 点赞 / 395 阅读 / 4186 字
温馨提示:
欢迎留言讨论!若内容或图片失效,请留言反馈。若不小心影响到您的利益,请联系我们删除。

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,这个过程是极慢极慢 的。

0

评论区