服务器报警:内存超95%

服务器报警:内存超95%

背景:

收到阿里云监控报警:服务器内存占用太高

和运维同事沟通了解后 这台机器上运行着另外一家公司的java项目, 这个项目启动后,内存会逐渐升高,直到95%就不变了,一直居高不下,这个问题已经很长时间了,由于涉及另外一家公司,而且似乎项目运行功能也没问题,只是多占些服务器资源,就一直没排查。

本着好奇的态度,我决定查查怎么回事

排查步骤:

  1. top发现java进场内存使用率比较高,首先想到的是看日志,但是并没有OOM的记录
  2. 按照一般的想法,还是要导出dump文件,看看内存里都是什么对象, 之前比较熟练是 用arthas导出

https://arthas.aliyun.com/doc/

有些命令记不清,每次用arthas都是到这个网页去找。

遇到一个问题:

[arthas@58205]$ heapdump arthas-output/dump.hprof

Dumping heap to arthas-output/dump.hprof ...

Heap dump file created

执行后找不到文件去哪儿了,查了半天发现 arthas-output 是 自动在tomcat的bin目录下

dump.hprof文件比较大 4G, 压缩tar -vczf 后下载下来

      3.用MAT打开dump.hprof文件,打开dominator_tree

发现最大是 java.lang.ref.Finalizer ,再点开 发现它好像是个链表结构,一直next

既然是链表结构,它节点本身是什么呢,看到referent 是 java.util.zip.ZipFile

查看ZipFile的outgoing

发现是arthas的jar,肯定是找错了。 又查了几个next 还是 arthas的jar, 肯定不是arthas引起的,那么到底是什么引起的呢 。 这个Finalizer 这么大,有没有办法统计出每个next里分别是什么对象呢, 去网上查资料,终于找到一个类似的帖子:
https://blog.csdn.net/shy_1023/article/details/135238034

帖子里提到可以用 OQL 查询

SELECT z.clazzName AS clazzName, z.maps AS Maps, z.maps.@length AS Count

FROM OBJECTS ( eval((SELECT s.sz AS clazzName, (SELECT OBJECTS m FROM java.lang.ref.Finalizer m WHERE (toString(m.referent.@clazz.@name) = s.sz)) AS maps FROM OBJECTS ( SELECT DISTINCT toString(h.referent.@clazz.@name) AS sz FROM java.lang.ref.Finalizer h ) s )) ) z

按F5执行发现 最多的是SocksSocketImpl

通过SocksSocketImpl incoming outgoing 一顿找 (incoming 是看哪些对象包含当前对象, outgoing是看 当前对象包含什么),终于找到了认识的 jdbc

再往下找就找不到了。

    4.然后就继续在网上找资料,终于找到了一个帖子:
https://blog.csdn.net/MakeContral/article/details/76615377

https://blog.csdn.net/u014365523/article/details/127513012

同时反编译了下 对方的代码,发现数据库连接没有使用线程池,里面有定时任务,1分钟执行一次, 一次里面有多个数据库查询操作, 每个查询总是新建数据库连接 关闭连接

大概理解的意思是: jdbc 连接 有重写 finalize() 方法,这导致资源释放不及时,好多对象被 java.lang.ref.Finalizer 引用, jvm不会立马杀掉它。

中间还尝试了 jcmd命令, dashborard命令

   5.另外发现似乎内存升高和 超大文件的IO有关系,沿着这个方向找也没查到特别有价值的资料。

 

解决方式:

跟踪了两天还是没有完全搞清楚原因,先尝试修改JVM参数,发现之前用的CMS收集器, 改为G1 收集器 -XX:+UseG1GC,据说G1 回收效率比较高,另外加了-XX:MaxDirectMemorySize=200m 防止使用Direct 内存太多。后续有时间再跟踪。

 

总结:

虽然没有彻底解决问题,但是通过这次跟踪 还是学到了一些知识:

  1. OQL的作用,之前只是知道并没有真正用过
  2. Finalizer 的原理, 链式结构,GC慢
  3. 理解了 数据库连接池化的好处
  4. JVM的一些参数
posted @ 2024-11-13 11:21  changlong2022  阅读(29)  评论(0编辑  收藏  举报