OOM问题原因:
根本原因是创建的对象数量超过JVM堆内存容量,且这些对象无法被GC回收
场景:
1.本地缓存了用户态,用户量急剧上升导致内存溢出,如使用HashMap本地缓存10万用户数据,每 个用户对象约2KB,导致至少200MB内存占用。
2.编写了死循环向集合添加元素的代码。
3.设计了静态集合但未实现元素清理功能。
4.JVM的堆内存设置太小不足以支撑项目的基本运行环境,如电商系统推荐-Xms4g -Xmx8g,而实际仅配置了-Xms512m -Xmx1g。
5.写了一个动态sql,当条件1是null的时候则查全表,全表数据量很多,导致内存溢出。
排查问题:
加两个jvm参数oom会自动把Dump日志下载下来
-XX:+HeapDumpOnOutOfMemoryError
-XX:HeapDumpPath=/path/to/dump.hprof
这种方式需要等程序出现oom的情况下才能拿到Dump日志,有些场景不适合,例如我就有过一次经历,服务到达一定内存的时候K8S自动重启了对应的服务,这种情况是不会触发oom报错的
所以我们就要用以下的方式来处理
间隔一段时间生成两次Heap Dump
jmap -dump:live,format=b,file=heap1.hprof <pid>jmap -dump:live,format=b,file=heap2.hprof <pid>
拿到日志后用工具分析
我这里用的是JDK自带的visualvm,同时也可以用Idea打开Dump日志也可以看到一些数据,我比较习惯用这个visualvm。
我这里是一个正常的dump日志,如果是异常的这里会显示哪个对象占用内存太多及对应的占用比例
这里还可以看到一些线程的信息,看到是哪里创建的这个对象,就可以找到对应的代码了