卡卷网
当前位置:卡卷网 / 每日看点 / 正文

一个技术总监需要知道JVM的GC机制吗,需要知道JVM是如何并行GC的吗?

作者:卡卷网发布时间:2025-01-09 18:34浏览数量:90次评论数量:0次

阿里P8技术官:搞Ja开发的,看懂JVM的GC志的很重要!!

前言

今天整理的这篇文章,整理自以前记录的常笔记。

刚开始接触JVM时,对待GC的志,是保持"逃避"态度的,线上部署的程序没有达到期望的运行效率,或是预期目标时,往往会把问题的矛头指向内存上。

是不是内存不够?

GC志怎么这么多?占用磁盘高达几个G?

不想看到打印怎么多,甚至暴力的将程序志屏蔽掉。

我也曾经这样干过,写过的程序,同样导致过内存溢出,甚至是主机宕机。

是的,ja中的回收的确帮我们省了很多事,我们不像C/C++程序员一样,

需要考虑分配(malloc)内存分配与(free)释放内存,但我相信每个ja开发的小伙伴都

会遇到GC问题,无论是在程序的性能优化,还是故障分析上。

我们应该在一次又一次的失误中获得经验和教训,而不是去逃避或是解决问题了事。同样的知识点,回顾两次,就会产生1+1>2的效应。

所以这篇文章我们来谈谈耳熟能详的JVM的GC志。

GC志是什么

首先来说一说GC的概念,GC就是回收(GarageCollection)的缩写。

何为?

没有任何引用指向的对象,被JVM视为。

当然,对应的判定算法有:引用计数算法、可达性分析算法。对应的回收算法有:标记清除、复制、标记整理、分代收集算法。

那GC的志是什么呢?

GC志是ja虚拟机产生的一种描述性的文本志。就像我们开发ja程序需要输出log志一样。JA虚拟机用GC志来描述,回收的情况。

minorGC和MajorGC

MinorGC,表示新生代GC,指发生在新生代的收集动作,所有的MinorGC都会触发全世界的暂停(stop-the-world),停止应用程序的线程,不过这个过程非常短。

MajorGC:老年代GC,指发生在老年代的GC,也称之为FullGC。

GC志有什么用

通过GC志,我们能直观的看到内存清理的基本工作过程。

了解回收的一些行为,何时在Young(年轻代)何时在回收Old(老年代),并且展示回收使用到多少资源。

尽管现在Ja程序的可视化监控工具已经很多了【介绍?】,但是GC志对于开发人员来说,是我们快速定位潜在的内存故障和性能瓶颈最直观的信息之一。

<>通过GC志我们能获取什么信息?

ES的GC分配失败(GCAllocationFaile)

遇到线上GC问题时的志也是很宝贵的分析素材,这里的GCAllocationFaile图片引用自一位群友的ES节点GC志。

GCAllocationFaile是我们经常遇到的一种GC志。

分配失败代表着在JVM的Eden区中没有更多的空间来分配对象了,这是minorGC的正常志。

那别光说不练,那我们来看看GCAllocationFaile的志内容是什么样的。

是不是感觉很乱?【抠脑袋图对话】

没关系,我们依次来分析分析。

我们按时间分割,可以知道,截图中一共有两行志,先来看志一:

2020-03-17T19:03:19.701+0800:6664.686: Totaltimeforwhichapplicationthreadswerestopped:0.0313360seconds ,Stoppingthreadstook:0.0000925seconds

毋庸置疑,首先映入眼帘的是带时区的志时间。

其次Totaltimeforwhichapplicationthreadswerestopped表示所有应用线程暂停了0.0313360秒。

其中等待所有应用线程到达【安全点】用了0.0000925秒。

暂停的这段时间,其实就是花在了GC上面。后续第二行的real=0.03se和这里相对应。

刚才提到了安全点,那简单提一提,我们知道在Ja的线程有几个不同的状态。也知道线程如果被“打断”会出现什么样的问题。所以对于设计者来说,需要让线程“跑”到安全点上,再停顿。当处于安全点时,线程的状态是确定的,这样JVM就可以安全的进行一些作,如执行回收。

安全点的位置包括:

如果有线程一直没有进入到安全点,就会导致GC时JVM停顿时间延长。

再来看志二:

1)2020-03-17T19:03:20.118+0800:6665.102: 2)[GC(AllocationFaile)2020-03-17T19:03:20.118+0800:6665.102: 3)[ParNewDesiredsvivorsize8716288ytes,newthreshold6(max6) 4)-age1:6826872ytes,6826872total 5)-age2:1060216ytes,7887088total 6):149828K->8895K(153344K),0.0361997se] 7)6272826K->6139400K(8371584K),0.0363166se] 8)[Times:user=0.07sys=0.00,real=0.03se]

第一行,为志输出的时间。

第二行,表明了进行了一次GC回收,注意,由于这里没有Full关键字,表明是一次MinorGC,并指明了GC的时间。AllocationFaile则表示GC的原因是在年轻代中没有了足够的空间来存储数据了。

第三行,ParNew同样指明了本次GC是发生在年轻代,并且使用的是ParNew收集器。该收集器采用复制算法回收内存,期间会停止工作线程,即StopTheWorld。

第三、四、五行,表示每次年轻代GC之后打印svivor区域内对象的年龄分布,threshold则表示设置的晋升老年代的年龄阈值为6。

第六行,分别表示GC前年轻代的使用容量,GC后该区域使用容量,括号内是该区域的总容量。最后是该内存区域GC耗时,单位是秒。

第七行,分别表示堆内存在回收之间的大小、堆内存在回收之后的大小,堆区的总大小。

可以看到在GC后,回收对象占很少。

第八行,显示三个耗时,分别是用户态耗时、内核态耗时、总耗时。

从以上信息我们可以分析得出以下结论:

本次GC新生代减少了:149828-8895=140933K。

堆内存区域共减少了:6272826-6139400=133426K。

图来自网络

再把两个等号后的结果相减:140933-133426=7507K

说明该次共有7507K(7.3M)内存从年轻代移到了老年代,可以看出来数量并不多,说明都是生命周期短的对象,只是这种对象有很多。

我们需要的是尽量避免FullGC的发生,让对象尽可能的在年轻代就回收掉,所以这里可以稍微增加一点年轻代的大小,让那7.3M的数据也保存在年轻代中。

ES的OldGC

上面介绍了年轻代的GC志,下面我们来说一说老年代的GC志,其实和年轻代分析的方法一样。

还是先列出志:

[gc][238384]overhead,spent[2.2s]collectinginthelast[2.3s] [2020-03-18T01:01:29,020][INFO][o.e.m.j.JvmGcMonitorServ] [eS][gc][old][238385][160772]dation[5s], collections[1]/[5.1s],total[5s]/[4.4d],memory[945.4m]->[958.5m]/[1007.3m], all_pools{[young][87.8m]->[100.9m]/[133.1m]}{[svivor][0]->[0]/[16.6m]}{[old][857.6m]->[857.6m]/[857.6m]}

直接来解释一下吧。第一行指明了这是第238384次GC在最近2.3s内花了2.2s用来做收集。

相信解读过年轻代的GC,理解第二行的含义并不复杂了。

[gc][本次是oldGC][这是第228385次GC检查][从JVM启动至今发生的第160772次GC]dation[本次检查到的GC总耗时5秒,可能是多次的加和],

collections[从上次检查至今总共发生1次GC]/[从上次检查至今已过去5.1秒],

total[本次检查到的GC总耗时为5秒]/[从JVM启动至今发生的GC总耗时为4.4天],

memory[GC前Heapmemory空间]->[GC后Heapmemory空间]/[Heapmemory总空间],

all_pools(分代部分的详情)

{[young区][GC前Memory]->[GC后Memory]/[young区Memory总大小]}

{[svivor区][GC前Memory]->[GC后Memory]/[svivor区Memory总大小]}{[old区][GC前Memory]->[GC后Memory]/[old区Memory总大小]}

ES的GC配置

-XX:+Printetails表示打印GC的详细志

-XX:+PrintateStamps表示需要展示打印GC的期时间

-XX:+PrintGCApplicationStoppedTime打印回收期间程序暂停的时间

志动,输出到指定的志文件中等等配置。

GC志图示

如果前面的介绍还没有太明白,这里附上两张GC志的图片,以后遇到需要阅读GC志的时候,可以用作工具查阅。

年轻代:

老年代:

总结(我的观点)

GC涉及到的知识点很多,本文可能只是冰山一角,从GC志出发分析,让读者了解,GC志中每个数字的变化,意味着什么。更多的,先前有介绍过线上OOM的一些排查思路和MAT性能分析工具在实际案例中的使用,同时希望各位多多结合实际的案例来分析,做好知识储备,即是线上出了GC的一些问题也能做到成竹在胸,调整出最优的JVM配置,提高线上程序的运行效率,尽量避免性能上的一些故障。最后在内容上做个小结

END

免责声明:本文由卡卷网编辑并发布,但不代表本站的观点和立场,只提供分享给大家。

评论 打赏
卡卷网

卡卷网 主页 联系他吧

请记住:卡卷网 Www.Kajuan.Net

相关推荐

欢迎 发表评论:

请填写验证码