加入收藏 | 设为首页 | 会员中心 | 我要投稿 淮安站长网 (https://www.0517zz.com.cn/)- 数据开发、人脸识别、智能机器人、图像处理、语音技术!
当前位置: 首页 > 站长资讯 > 外闻 > 正文

脚本遭遇异常时如何安全退出

发布时间:2021-02-15 11:49:09 所属栏目:外闻 来源:互联网
导读:问题根因 我们在调用wcs前将驼峰字段的实体类序列化成下划线字段,**这需要使用fastjson的SerializeConfig,而我们在静态方法中对其进行了实例化。SerializeConfig创建时默认会创建一个ASM代理类用来实现对目标对象的序列化。也就是上面被频繁创建的类com.al

问题根因

我们在调用wcs前将驼峰字段的实体类序列化成下划线字段,**这需要使用fastjson的SerializeConfig,而我们在静态方法中对其进行了实例化。SerializeConfig创建时默认会创建一个ASM代理类用来实现对目标对象的序列化。也就是上面被频繁创建的类com.alibaba.fastjson.serializer.ASMSerializer_1_WlkCustomerDto,如果我们复用SerializeConfig,fastjson会去寻找已经创建的代理类,从而复用。但是如果new SerializeConfig(),则找不到原来生成的代理类,就会一直去生成新的WlkCustomerDto代理类。

下面两张图时问题定位的源码:
 

「可以看出,元空间在不断上涨,并且已装入的类随着调用量的增加也在不断上涨,呈现正相关趋势。」

柳暗花明又一村

问题一下子明朗了起来,「随着每次接口的调用,极有可能是某个类都在不断的被创建,占用了元空间的内存」。

观察JVM类加载情况 -verbose

在调试程序时,有时需要查看程序加载的类、内存回收情况、调用的本地接口等。这时候就需要-verbose命令。在myeclipse可以通过右键设置(如下),也可以在命令行输入java -verbose来查看。
 

上图中给我们的信息,都不能很明显的看出问题,至少我当时依然不能通过这几次信息看出问题。

排查似乎陷入了僵局。

山重水复疑无路

在排查陷入停滞的时候,我们得到了来自WCS和SCF方面的回复,「两方都确定了他们的封装没有内存泄漏的存在」,WCS方面没有使用直接内存,而SCF虽然作为底层RPC协议,但是也不会遗留这么明显的内存bug,否则应该线上有很多反馈。

查看JVM内存信息 jmap

此时,找不到问题的我再次新开了一个沙箱容器,运行服务进程,然后运行jmap命令,看一看JVM内存的「实际配置」:
 

「问题来了:为何内存会不断往上走吃满内存呢?」

当时猜测是由于JVM进程并没有对于直接内存大小进行限制(-XX:MaxDirectMemorySize),所以堆外内存不断上涨,并不会触发FullGC操作。

「上图能够得出两个结论:」

  • 在内存泄露的接口调用量很大的时候,如果恰好堆内老生代等其他情况一直不满足FullGC条件,就一直不会FullGC,直接内存一路上涨。
  • 而在平时低调用量的情况下, 内存泄漏的比较慢,FullGC总会到来,回收掉泄露的那部分,这也是平时没有出问题,正常运行了很久的原因。

「由于上面提到,我们进程的启动参数中并没有限制直接内存,于是我们将-XX:MaxDirectMemorySize配置加上,再次在沙箱环境进行了测验。」

结果发现,进程占用的物理内存依然会不断上涨,超出了我们设置的限制,“看上去”配置似乎没起作用。

这让我很讶异,难道JVM对内存的限制出现了问题?

「到了这里,能够看出我排查过程中思路执着于直接内存的泄露,一去不复返了。」

「画外音:我们应该相信JVM对内存的掌握,如果发现参数失效,多从自己身上找原因,看看是不是自己使用参数有误。」

直接内存分析

为了更进一步的调查清楚直接内存里有什么,我开始对直接内存下手。由于直接内存并不能像堆内存一样,很容易的看出所有占用的对象,我们需要一些命令来对直接内存进行排查,我有用了几种办法,来查看直接内存里到底出现了什么问题。

查看进程内存信息 pmap

pmap - report memory map of a process(查看进程的内存映像信息)

pmap命令用于报告进程的内存映射关系,是Linux调试及运维一个很好的工具。


(编辑:淮安站长网)

【声明】本站内容均来自网络,其相关言论仅代表作者个人观点,不代表本站立场。若无意侵犯到您的权利,请及时与联系站长删除相关内容!

    热点阅读