java.lang.OutOfMemoryError: Java heap space
出现这种异常是因为 堆内存不足
原因
1.请求创建一个超大对象。(通常为超大List)
2.内存泄漏,在多次GC后,还是找不到一块完整的内存来存放当前对象
3.过度使用终结器(Finalizer),该对象没有立即被 GC。(重写finalize,造成频繁GC。 c++程序员 调用析构函数,析构函数 用来delete 对象)
可能出现的原因
针对大部分情况,通常只需要通过设置 最小堆内存 -Mms 最大堆内存 -Xmx 参数调高 JVM 堆内存空间即可,如果未解决。
1、如果是超大对象,可以检查其合理性,比如是否一次性查询了数据库全部结果,而没有做结果数限制。
2、如果是业务峰值压力,可以考虑添加机器资源,或者做限流降级。
3、如果是内存泄漏,需要找到持有的对象,修改代码设计,比如关闭没有释放的连接。
4、Mybatis 三级缓存默认开启,在一个循环里大量查询会导致内存不能释放,如果不需要考虑效率,三级缓存可以暂时关闭。
5、tomcat http-header-size过大问题,设置为默认值 8KB
6、new 大量线程,会产生 native thread OOM
排查问题的方法
- Top 命令 查询 linux 服务器运行的 Java 进程。
- Top -Hp 进程号 查询当前进程下 所有线程。哪个线程CPU和内存占比高
- jps定位具体java进程(线程池最好定义有意义的name)
jstack 定位线程状况,重点关注:WAITING BLOCKED eg.
waiting on <0x0000000088ca3310> (a java.lang.Object)
假如有一个进程中100个线程,很多线程都在waiting on <xx> ,
一定要找到是哪个线程持有这把锁,搜索jstack dump的信息,找<xx> ,
看哪个线程持有这把锁RUNNABLE
4.jstat -gc 动态观察gc 情况
- jstat -gc 进程号 500 每500毫秒打印一次gc信息
- jconsole (jdk自带,需要配置JMX,指定ip、端口)
- jvisualVM (jdk自带) jvisualvm远程连接
https://www.cnblogs.com/liugh/p/7620336.html - Jprofiler(最好用,收费)
- jmap - histo 进程号 | head -20,查找有多少对象产生,只需要打印前二十行就好
6.jmap -dump:format=b,file=xxx pid
线上环境,内存特别大,jmap命令容易对进程产生很大影响,甚至卡顿。
- 设定参数-XX:+HeapDumpOnOutOfMemoryError,OOM的时候会自动产生堆转储文件
- 对发生OOM的服务器做隔离,再运行jmap命令定位问题
7.使用MAT / jhat /jvisualvm 进行dump文件分析
- https://www.cnblogs.com/baihuitestsoftware/articles/6406271.html
- jhat -J-mx512M xxx.dump
http://ip:端口
拉到最后:找到对应链接
可以使用OQL查找特定问题对象