JVM提供了很多处理OutOfMemoryError
有用的参数。在本文中,我们介绍讲解一下这些参数。当你再遇到OutOfMemoryError
进行故障排查时会很有帮助,这些参数如下:
- -XX:+HeapDumpOnOutOfMemoryError -XX:HeapDumpPath
- -XX:OnOutOfMemoryError
- -XX:+ExitOnOutOfMemoryError
- -XX:+CrashOnOutOfMemoryError
下面我们来详细的看下每个参数的意义和用法。
1. -XX:+HeapDumpOnOutOfMemoryError -XX:HeapDumpPath
Heap Dump
就是内存的一个映像,它包含了内存中存在的对象的详细信息,包括对象包含的实际数据、对象之间的引用关系等等。Heap Dump
是用来诊断内存相关问题最重要的工具。
为了诊断OutOfMemoryError
或任何与内存相关的问题,当发生内存溢出或者将要发生内存溢出的时候,我们首先需要去捕获Heap Dump
,在发生内存溢出的时候很难手动捕获Heap Dump
,因为我们不知道什么时候会抛出OutOfMemoryError
,但是,在命令行中启动应用程序时,可以通过传递以下JVM参数来自动执行捕获Heap Dump
的操作:
-XX:+HeapDumpOnOutOfMemoryError and -XX:HeapDumpPath={HEAP-DUMP-FILE-PATH}
例子如下:
-XX:+HeapDumpOnOutOfMemoryError -XX:HeapDumpPath=/crashes/my-heap-dump.hprof
-XX:HeapDumpPath
指定了内存映像文件的存储路径。
只要给JVM传递了这2个参数,当发生内存溢出的时候,JVM会自动在指定目录下生成内存映像文件。
获取内存映像文件后,就可以使用HeapHero和Eclipse MAT之类的工具来分析Heap Dump
了。
2. -XX:OnOutOfMemoryError
当发生内存溢出的时候,还可以让JVM调用任一个shell脚本。大多数时候,内存溢出并不会导致整个应用都Crash
掉,但是,一旦发生OutOfMemoryError,最好重新启动应用程序。
因为OutOfMemoryError
可能会使应用程序处于不稳定状态。一个不稳定的应用可能会提供错误的响应。使用举例:
-XX:OnOutOfMemoryError=/scripts/restart-myapp.sh
传递此参数时,每当抛出OutOfMemoryError
时,JVM就会调用/scripts/restart-myapp.sh
脚本。在此脚本中,您可以编写代码以优雅地方式重新启动应用程序。
3. -XX:+CrashOnOutOfMemoryError
如果给JVM传递了这个参数时,当发生OutOfMemoryError
的时候JVM就会退出,同时,JVM会产生文本和二进制格式的崩溃日志(如果启用了核心文件)。但是,就我个人而言不建议配置上这个参数的,我们应该是以一种优雅的方式退出程序,粗暴的退出方式可能会损害正在进行的事务。
以前遇到过有个应用配置了-XX:+CrashOnOutOfMemoryError
这个参数,当发生内存溢出的时候,JVM立马就退出了,并且在控制台有如下日志打印:
Aborting due to java.lang.OutOfMemoryError: GC overhead limit exceeded
#
# A fatal error has been detected by the Java Runtime Environment:
#
# Internal Error (debug.cpp:308), pid=26064, tid=0x0000000000004f4c
# fatal error: OutOfMemory encountered: GC overhead limit exceeded
#
# JRE version: Java(TM) SE Runtime Environment (8.0_181-b13) (build 1.8.0_181-b13)
# Java VM: Java HotSpot(TM) 64-Bit Server VM (25.181-b13 mixed mode windows-amd64 compressed oops)
# Failed to write core dump. Minidumps are not enabled by default on client versions of Windows
#
# An error report file with more information is saved as:
# C:\workspace\tier1app-svn\trunk\buggyapp\hs_err_pid26064.log
#
# If you would like to submit a bug report, please visit:
# http://bugreport.java.com/bugreport/crash.jsp
#
从日志中可以看出来,在C:\workspace\tier1app-svn\trunk\buggyapp\hs_err_pid26064.log
目录下生成了崩溃日志文件,它里面包含了崩溃的详细信息。可以使用诸如fastThread的工具来分析hs_err_pid
这个日志, 但是hs_err_pid
中存在的大多数时间信息都是非常基本的,不足以对OutOfMemoryError
的原因进行定位。
4. -XX:+ExitOnOutOfMemoryError
传递此参数时,抛出OutOfMemoryError
时,JVM将立即退出。如果您想终止应用程序,则可以传递此参数。但就我个人而言,我不希望配置该参数,因为我们应该始终以实现正常退出为目标。突然退出可能/将危害正在进行的事务。
我使用此-XX:+ ExitOnOutOfMemoryError
JVM参数运行了相同的内存泄漏程序。与-XX:+ CrashOnOutOfMemoryError
不同,此JVM参数不会生成任何文本/二进制文件,直接就退出了。
英文原文见: blog.gceasy.io

本文由 空心菜 创作,采用 知识共享署名4.0 国际许可协议进行许可
本站文章除注明转载/出处外,均为本站原创或翻译,转载前请务必署名
最后编辑时间为: Dec 17, 2019 at 03:56 pm