JAVA 内存泄露、溢出的检查方法、工具介绍
问题发现:
在我们运行的一个项目上线运营后发现运行两天左右就会报内存溢出,只有重启
tomcat 才能恢复服务,异常信息如下:
java.lang.OutOfMemoryError: GC overhead limit exceeded
java.lang.OutOfMemoryError: Java heap space
原因分析:
在此之前必须先介绍一下关于 jvm 的内存控制,JVM 即 java 虚拟机,它运行时候
占用一定的内存,其大小是有限定的,如果程序在运行时 jvm 占用的内存大于某个限
度,则会产生内存溢出,也就是“java.lang.outofmemoryerror”。如果 jvm 内存的
没有限度,并且有无限大的内存,那 jvm 就永远不会出现内存溢出了。很明显无限的
内存是不现实的,但是一般情况下我们程序运行过程所需要的内存应该是一个基础固
定的值,如果仅是因为我们的项目所需内存超过了 jvm 设置内存值导致内存溢出,那
么我们可以通过增大 jvm 的参数设置来解决内存溢出的问题。详细处理可参考 java
jvm 的如下参数设置:-Xms -Xmx -Xmn -Xss
-Xms: 设置 JVM 初始内存,此值可以设置与-Xmx 相同,以避免每次垃圾回收完成
后 JVM 重新分配内存。
-Xmx:设置 JVM 最大可用内存。
-Xmn:设置年轻代大小,整个堆大小=年轻代大小+年老代大小+持久代大小.持
久代一般固定大小为 64m,所以增大年轻代后,将会减小年老代大小.此值对系统性能影
响较大,Sun 官方推荐配置为整个堆的 3/8.
-Xss:设置每个线程的堆栈大小.在相同物理内存下,减小这个值能生成更多的线程.
但是操作系统对一个进程内的线程数还是有限制的,不能无限生成。
在 jvm 参数调试过程中,发现分配最大内存数超过 1G 后,仍然会产生内存溢出
的现象,而估计其正常分配使用的内存应该不会超过 1G,那么由此可以基本断定其存
在内存泄露现象,也就是一些原来分配的不再使用的内存不能被 java 的垃圾回归所回
收,导致不断占用原分配的内存而不释放,导致不断申请更多的内存直到超过内存设
评论14