# OOM(OutOfMemoryError)故障排查

当系统启动后一起正常,但是使用一段时间后或者用户量多了之后就卡了,一直没响应,CPU使用率很高,重启服务后又正常了,这时很可能就是OOM了。

# OutOfMemoryError原因

TIP

本章节中涉及到操作JVM启动参数的操作请参考Tomcat设置启动环境变量

# 1.java.lang.OutOfMemoryError: Java heap space

堆内存不够用了,堆内存32位系统最好大于1G,64位最好大于2G,但不要太大,太大会导致gc慢,更不要大于或接近物理内存大小,否则会使用交换空间虚拟内存严重降低系统性能。

解决方法

建议增大JVM启动参数-Xmx=2048m

# 2.java.lang.OutOfMemoryError: PermGen space

TIP

这个异常只对JDK7及以下版本,JDK8已经去掉了PermGen space,改为Metaspace了。JDK8最好设置参数-XX:MaxMetaspaceSize=256m,避免JVM无节制的使用内存。

PermGen space的全称是Permanent Generation space,是指内存的永久保存区域, 这块内存主要是被JVM存放Class和Meta信息的,Class在被Loader时就会被放到PermGen space中, 它和存放类实例(Instance)的Heap区域不同,GC(Garbage Collection)不会在主程序运行期对 PermGen space进行清理,所以如果你的应用中有很多CLASS的话(包括Spring动态产生的类),就很可能出现PermGen space错误。

解决方案

建议增加JVM启动参数-XX:MaxPermSize=256m

MaxPermSize参数表示JVM可用的最大PermGen space,MaxPermSize参数大小为32M,MaxPermSize不会占用Max Heap Size(-Xmx)中设置的大小,如果设置:-Xmx1024m -XX:MaxPermSize=256m,那么Max Heap Size是1024m,不是1024m-256m

# 3.java.lang.OutOfMemoryError: GC overhead limit exceeded

TIP

java.lang.OutOfMemoryError: GC overhead limit exceeded,这个是JDK6新添的错误类型。是发生在GC占用大量时间为释放很小空间的时候发生的,是一种保护机制。

JVM GC过程耗时很久但只回收了不到2%的可用内存,如果已经设置了Xmx参数,那么可能是由于某些用户操作导致系统长时间占用大量内存无法GC。在JSP导入大excel时,也会出现此错误提示。

解决方案

增加JVM启动参数-XX:-UseGCOverheadLimit,更多内容可参考网页调优JVM内存 (opens new window)

# 4.其他

其他情况 (opens new window)

# OutOfMemoryError故障确诊

当系统cpu消耗很高,而且线程都在做gc的时候可能就是有OOM了,如何确诊呢:

# 看看最忙的线程在干啥

top //显示耗费cpu的进程
top -p 进程号 -H //显示这个进程内最好分cpu的线程,把列出的pid转换成小写16进制可在JVM堆栈中找到堆栈信息

top

pid

# 设置gc日志记录,并分析gc日志

给JVM设置gc日志记录:-verbose:gc -Xloggc:garbage-collection.log(参见oracle官方说明 (opens new window)),然后使用网站gceasy (opens new window)分析日志:

分析日志1

分析日志2

当提示Our analysis tells that your application is suffering from memory leak. It can cause OutOfMemoryError, JVM to freeze, poor response time and high CPU consumption. 时就说明有内存漏洞了。

# OutOfMemoryError故障排查

# 参数自动导出Heapdump

如果已经进行了合理的XmxXX:MaxPermSize设置,还是出现OutOfMemoryError,那需要咨询研发工程师排查问题,为了帮助研发工程师解决问题,增加如下JVM参数以便在出现OOM的时候获得JVM的HeapDump文件:

-XX:+HeapDumpOnOutOfMemoryError -XX:HeapDumpPath=/path/to/store/dumpfiles

当下次出现OOM后JVM会产生heapdump文件在/path/to/store/dumpfiles 目录下,请自行修改/path/to/store/dumpfiles的具体位置,确保/path/to/store/dumpfiles是一个存在的目录,且启动JVM的系统用户有权限写这个目录,如果下次出现OOM,把HeapDump文件(很大,需压缩后)发送给研发工程师。

# jmap命令导出Heapdump

如果系统日志已经发现OOM错误,而未配置-XX:+HeapDumpOnOutOfMemoryError参数,并且内存占用比较高,可以通过jdk自带的jmap命令导HeapDump。

./jmap -dump:live,format=b,file=heap.hprof <pid>

# 分析heapdump文件

生产环境内存一般配置比较高比如10G左右,产生的heapdump文件比较大,可以使用现场测试环境服务器安装MAT,采用命令行进行分析,把分析的结果发给研发进行排除问题。

MAT下载

点击此处 (opens new window)下载MAT,选择Linux(X86_64/GTK+).

配置MAT

解压之后,需要修改MAT的配置文件,打开MemoryAnalyzer.ini文件,修改-Xmx的值,使其大于hprof文件的大小,建议是其2倍大小。

执行分析命令

./ParseHeapDump.sh heap.hprof org.eclipse.mat.api:suspects

执行以后会生成 xxxx_Suspects.zip 的压缩包,解压后打开其中的html页面即可看到结果。

是否有帮助?
0条评论
评论