我是靠谱客的博主 陶醉钥匙,最近开发中收集的这篇文章主要介绍GC日志分析,觉得挺不错的,现在分享给大家,希望可以做个参考。

概述

目录

读日志

GC (minor )日志

Full GC 日志

concurrent mode failure

promotion failure

Allocation Failure

Evacuation Failure

Humongous Allocation


读日志

GC (minor )日志

Full GC 日志

concurrent mode failure

concurrent mode failure,主要是由于cms的无法处理浮动垃圾(Floating Garbage)引起的。这个跟cms的机制有关。cms的并发清理阶段,用户线程还在运行,因此不断有新的垃圾产生,而这些垃圾不在这次清理标记的范畴里头,cms无法再本次gc清除掉,这些就是浮动垃圾。由于这种机制,cms年老代回收的阈值不能太高,否则就容易预留的内存空间很可能不够(因为本次gc同时还有浮动垃圾产生),从而导致concurrent mode failure发生。可以通过-XX:CMSInitiatingOccupancyFraction的值来调优。

concurrent mode failure是两个原因:

  • 在 CMS 启动过程中,新生代提升速度过快,老年代收集速度赶不上新生代提升速度,在执行CMS GC的过程中同时有对象要放入老年代,而此时老年代空间不足造成的
  • 在 CMS 启动过程中,老年代碎片化严重,无法容纳新生代提升上来的大对象

发送这种情况,应用线程将会全部停止(相当于网站这段时间无法响应用户请求),进行压缩式垃圾收集(回退到 Serial Old 算法)

解决办法:

  • 新生代提升过快问题:(1)如果频率太快的话,说明空间不足,首先可以尝试调大新生代空间和晋升阈值。(2)如果内存有限,可以设置 CMS 垃圾收集在老年代占比达到多少时启动来减少问题发生频率(越早启动问题发生频率越低,但是会降低吞吐量,具体得多调整几次找到平衡点),参数如下:如果没有第二个参数,会随着 JVM 动态调节 CMS 启动时间
-XX:CMSInitiatingOccupancyFraction=68 (默认是 68)
-XX:+UseCMSInitiatingOccupancyOnly
  • 老年代碎片严重问题:(1)如果频率太快或者 Full GC 后空间释放不多的话,说明空间不足,首先可以尝试调大老年代空间(2)如果内存不足,可以设置进行 n 次 CMS 后进行一次压缩式 Full GC,参数如下:
-XX:+UseCMSCompactAtFullCollection:允许在 Full GC 时,启用压缩式 GC
-XX:CMSFullGCBeforeCompaction=n     在进行 n 次,CMS 后,进行一次压缩的 Full GC,用以减少 CMS 产生的碎片

promotion failure

promotion failure,是在minor gc过程中,survivor的剩余空间不足以容纳eden及当前在用survivor区间存活对象,只能将容纳不下的对象移到年老代(promotion),而此时年老代满了无法容纳更多对象,通常伴随full gc,因而导致的promotion failure。这种情况通常需要增加年轻代大小,尽量让新生对象在年轻代的时候尽量清理掉。

Allocation Failure

表明本次引起GC的原因是因为在年轻代中没有足够的空间能够存储新的数据了

Evacuation Failure

当没有更多的空闲region被提升到老一代或者复制到幸存空间时,并且由于堆已经达到最大值,堆不能扩展,从而发生Evacuation Failure。对于G1 GC,它是非常耗时的。 

 a.对于成功复制的对象,G1需要更新引用,并且该region被一直引用。

 b.对于未成功复制的对象,G1将自动转发它们,并保留这些region。

解决方案:

①.不要过度加一些jvm参数。比如-Xmn,这个参数会限制G1的参数的自动扩展。可以仅使用-Xms,-Xmx和暂停时间目标-XX:MaxGCPauseMillis,删除任何额外的堆大小,例如-Xmn,-XX:NewSize,-XX:MaxNewSize,-XX:SurvivorRatio等。

②.如果问题仍然存在,则增加JVM堆大小(即-Xmx)。

③.如果您无法增加堆大小,并且您注意到marking cycle没有足够早地开始回收老一代,那么请减少-XX:InitiatingHeapOccupancyPercent。默认值是45%。减小该值将提前开始marking cycle 。另一方面,如果marking cycle 提前开始并且未收回,请将-XX:InitiatingHeapOccupancyPercent阈值增加到默认值以上。

④.如果并发marking cycle准时开始,但需要很长时间才能完成,那么使用属性'-XX:ConcGCThreads'增加并发标记线程数的数量。默认是GC Workers: 1 ,单线程执行。

⑤.如果有大量“空间耗尽(to-space exhausted)”或“空间溢出(to-space overflow)”GC事件,则增加-XX:G1ReservePercent。默认值是Java堆的10%。注意:G1 GC将此值限制在50%以内。

Humongous Allocation

它是由'G1 Humongous Allocation'造成的。大型对象(Humongous )是大于G1中region大小50%的对象。频繁大型对象分配会导致性能问题。如果region里面包含大量的大型对象,则该region中最后一个具有巨型对象的区域与区域末端之间的空间将不会使用。如果有多个这样的大型对象,这个未使用的空间可能导致堆碎片化。直到jdk1.8u40之前,这些巨型对象的回收只在full GC期间完成。在较新的JVM中,对这些对象的清理放在了清理阶段。

解决方案:

①.可以加大region的大小,设置-XX:G1HeapRegionSize=n,但是这个参数需要设置为2的幂次方,最小值是1M,做大值是32M。

②.如果可以的话增加JVM堆大小(即-Xmx -Xms)。

 

gc日志在线分析工具

https://fastthread.io/

https://gceasy.io/

 

 

 

 

 

 

 

最后

以上就是陶醉钥匙为你收集整理的GC日志分析的全部内容,希望文章能够帮你解决GC日志分析所遇到的程序开发问题。

如果觉得靠谱客网站的内容还不错,欢迎将靠谱客网站推荐给程序员好友。

本图文内容来源于网友提供,作为学习参考使用,或来自网络收集整理,版权属于原作者所有。
点赞(47)

评论列表共有 0 条评论

立即
投稿
返回
顶部