一、定义
内存溢出:OutOfMemoryError,是指因内存不够,导致操作新对象没有剩余空间。会导致频繁fullgc出现STW从而导致性能下降。
内存泄漏:指用malloc或new申请了一块内存,但是没有通过free或delete将内存释放,导致这块内存一直处于占用状态。
二、主要外在体现
- 应用程序长时间连续运行时性能下降;
- CPU使用率高,甚至到100%;
- 频繁fullgc,各种诸如接口超市等报警;
- 应用程序偶尔会耗尽连接对象;
查看应用程序full gc时间:jstat -gc pid 间隔时间 显示次数:
三、造成OOM的原因
- 一次性申请的对象太多。比如查数时表数据太多一次性到内存中处理,需要定位到具体的代码再优化;
- 内存资源耗尽未释放。比如一些连接、线程等,应用完后释放,且用线程池的概念;
- 本身资源不够。本身要处理一些日常的大对象工作,可以用jmap -heap 可以查看服务资源情况。
jmap -heap命令界面
四、定位OOM
1、系统已经OOM宕机
1.1、提前设置JVM参数
-XX:+HeapDumpOnOutOfMemoryError - XX:HeapDumpPath
在java程序启动时在jvm参数增加OOM时到处dump文件的命令,在应用发生OOM后会导出一个堆的dump文件到指定目录。需要在启动服务时设置参数,如果事前没有设置,出现OOM宕机后会无据可查。文件会比较大,因为会记录系统运行过程中所有的对象的信息,所以要保证磁盘空间较大。
java -Xms10M -Xmx10M -XX:+HeapDumpOnOutOfMemoryError - XX:HeapDumpPath=xxx -jar
1.2、工具:
visualvm:载入文件时,要注意文件类型是dump文件。主要看类目录下找到占内存最大且是自己开发创建的实例。双击进入后,随便定位其中一个实例,引用下找到GC Root,单击右键选择在线程中显示,就可以定位到具体的代码位置了。
2、运行中还未OOM
2.1、导出dump文件
jmap -dump:fromat=b,file=xxx.hprof 进程号(jps查看进程号);
导出OOM dump文件会导致一次full gc,会造成一次STW,所以是接收到频繁full gc或内存过高的告警后,为排查问题时快速定位OOM才去操作。
2.2、Arthas工具线上诊断。
可参考链接:Java诊断工具-Arthas保姆级教程_arthas定位内存泄漏-CSDN博客
2.3、jmap -histo:live 进程ID |head -20
会排序显示最占内存的对象,与dump文件查看实例差不多。|head -20:打印前20行。
3、结合jvisualvm进行调试
查看最多跟业务有关对象->找到GCROOT->查看线程栈,就可以快速定位业务代码了。