又是一次客户问题,客户生产上服务始终无缘掉线,理解了半天,大概率是 oom 导致的,因为零碎主动打进去了内存 dunp(会心一笑);如果别的故障导致的问题,系统日志早提醒了,还能找咱们帮忙看吗!
拿到客户的 dump 文件废了一天的工夫,这里吐槽一下,就不能搞一个直达零碎什么的,只能通过一个备案过的移动硬盘来考货色,一个部门那么多人想借用一下等了老半天,还是等人家上班后,才轮到咱们借用了一下。要是生产上考下来点敏感信息啥的谁晓得,不知道安全部门咋想的。
一、问题景象
一番周折,对拿到的 dump 剖析了一下,看到 java.util.ArrayList 占用了好多的空间。
二、排查过程
具体细看了一下全部都是这个实体类导致的吗,【com.cupdata.upcoas.model.Apply】对这个实体类做了下查问,看看发现了什么,这个对象有大略 30W 个,每个均匀大略 8k,那最初这个对象不是占用了大略 \(300000*8/1024/1024=2.28G \)
理解到客户这台服务器是 4C16G 的机器,java 过程没有给 -Xms -Xmx 参数。因为 JVM 最大调配的内存由 -Xmx 指定,默认是物理内存的 1 /4。排查发现该过程是没有配置 -Xms -Xmx 的,所以过程最大内存也就 4G。
三、解决方案
1、手动设置 jvm 堆内存大小,增加如下启动参数:
-Xms6g -Xmx6g -XX:+UseG1GC -XX:+PrintGCDetails -XX:+HeapDumpOnOutOfMemoryError
- 堆内存视物理内存和理论状况可上下调整。对于 6G 以上的大堆,应用 G1 垃圾收集器会有更好的性能体验;
- 配置产生内存溢出的时候主动生成转储文件,以便剖析问题;
- 配置 gc 日志,以便剖析 gc 问题;
2、设置 ArrayList 初始化大小
如果 Apply 对象是保留在自定义创立的 ArrayList 中的,在 new ArrayList 数组的时候配置初始化大小,防止其主动扩容。
四、思考
这个只是对这个 dump 文件进行的一次初步剖析,具体前面会在到客户现场排查,等着前面更新吧。