大量NullPointExcepiton导致老年代被打满,引起巨量Full GC使应用程序停止

一、前言

我们线上有个应用程序,大约每隔一个星期左右就会出现假死现象,也就是进程在,但是实际程序已经挂掉了,开始排查没有发现什么问题,然后就写了一个每周重启进程的脚本,定时重启进程,好了一段时间。大约在一周前,发现重启脚本也不好使了,每次重启后,大约不到十五分钟进程就会挂掉,意识到问题的严重性了,故开始以下的排查:

二、正文

1、首先通过jmap命令看下堆中各个区域信息是否正常,命令如下:

jmap -heap pid

结果如下:

在这里插入图片描述

我去,这年轻代、老年代和永久代都已经炸了。。。

我首先想到的是永久代空间太小了,因为是默认值,只有20M-82M,所用利用-XX:PermSize和-XX:MaxPermSize参数设置初始值和最大值。设置好了,重启进程,又跑了一段时间,出现以下结果:

在这里插入图片描述

额,其他都代都还可以,就是老年代又被打满了。。。

正常的话,老年代快满的时候,会进程Full GC的,但是看上面的结果Full GC好像是没有起作用。

2、使用jstat命令输出年轻代,老年代已经使用容量的百分比和gc次数,命令如下:

jstat -gcutil pid 1000 100

上面的含义就是1000毫秒统计一次gc情况,统计100次。(pid是要查看的进程)

结果如下:

在这里插入图片描述

这是修改完参数,大约跑了一个晚上的情况。

what???将近7000的Full GC,你咋不上天呢???程序还能跑才怪呢。。。

然后我又重启了进程,重启观察GC的变化,结果变化如下:

在这里插入图片描述

在这里插入图片描述

在这里插入图片描述

以上三个大约运行了半个多小时,可以看到老年代已经满了,而且Full GC已经多到不行了,程序实际已经假死了。

因为我们用的GC回收器是 Parallel Scavenge + Parallel Old,Full GC的时候会导致STW,也就是只有GC线程在工作,工作线程被挂起,所以我们的程序出现了一直假死的现象。

3、其实我们后台是之前也是有那种NullPointExcepiton错误日志的,但是排查的时候发下没有影响正常的业务,我们的业务属于和终端交互的,通过tr069协议做业务下发的,我看这个终端是正常开户的,所以就没有太在意,但正是这个NullPointExcepiton导致我们的程序假死。PS:上面说的和终端的交互可能大家没做的都不太懂,不过没关系,你们就知道是发生了大量的NullPointExcepiton异常就好了。

4、为什么大量的NullPointException会把老年代打满,造成巨量的Full GC呢?

首先我们明确一个概念,如何识别垃圾?目前虚拟机用的都是可达性分析算法,也就是以GC Roots的对象为起点出发,形成一个引用链,如果相关的对象不在以GC Roots为起点的引用链中,则会被认为是垃圾,就会被GC回收。

好了,明确了如何识别垃圾这个概念,我们来说下为啥大量NullPointException会导致老年代被打满?因为NullPointException就是一个GC Roots对象啊,在周志明的《深入理解Java虚拟机》书中,有以下一段:

在这里插入图片描述

所以,有大量以NullPointException为GC Roots的对象,不能够被GC回收,导致最终都进入老年代,当老年代满了,就要进行Full GC,但是由于NullPointException实在太多了,导致巨量的Full GC,所以我们的程序很快就出现假死现象了。

接下来就是排查NullPointException的问题了,实际上是程序的bug导致的,这个就不在这里详细说了。

三、总结

遇到问题,就重启服务器,这个只是治标不治本的方法啊,我们还是要找到问题本质所在。还有就是一定要注意后台错误日志中出现的问题,也许一个小问题,不会影响什么,但是当大量同样的问题出现时,就会造成很严重的问题,毕竟千里之堤毁于蚁穴。

最后引用我很佩服的一个人经常说的话:你知道的越多,你不知道的越多!

  • 3
    点赞
  • 4
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值