JVM 中提供了非常有用的 OutOfMemoryError 参数。在本文中,我们将重点介绍这些 JVM 参数。在您对 OutOfMemoryError 进行故障排除时,本文可能会非常实用。这些 JVM 参数有:
- -XX:+HeapDumpOnOutOfMemoryError -XX:HeapDumpPath
- -XX:OnOutOfMemoryError
- -XX:+ExitOnOutOfMemoryError
- -XX:+CrashOnOutOfMemoryError
下面我们就来详细聊聊吧。
(1). -XX:+HeapDumpOnOutOfMemoryError -XX:HeapDumpPath
堆内存转储文件基本上就是内存的快照。其中包含与存在于内存中的对象、对象中的实际数据以及对这些对象的引用的详细信息。在对内存问题进行故障排除的过程中,堆内存转储文件是十分有用的工具。
为了对 OutOfMemoryError 或任意内存相关问题进行诊断,您需要捕获程序在出现 OutOfMemoryError 那一瞬间或之前极短时间内的转储文件。手动捕获此类转储文件是十分困难的,因为我们不知道程序会在何时抛出 OutOfMemoryError。不过,捕获工作可自动进行,只需在命令行中启动程序时传递以下参数即可:
-XX:+HeapDumpOnOutOfMemoryError and -XX:HeapDumpPath={HEAP-DUMP-FILE-PATH}
示例:
-XX:+HeapDumpOnOutOfMemoryError -XX:HeapDumpPath=/crashes/my-heap-dump.hprof
您需要在“OutOfMemoryError”指定用于存储堆内存转储文件的路径。
传递了这两个 JVM 参数后,在抛出 OutOfMemoryError 时堆内存转储文件将被自动捕获并写入指定的文件路径。
捕获堆内存转储文件后,您可使用 HeapHero、Eclipse MAT 等工具来对其进行分析。
(2). -XX:OnOutOfMemoryError
您可对 JVM 进行配置以使其在抛出 OutOfMemoryError 时调用任意脚本。大多数情形中,OutOfMemoryError 不会使得程序崩溃。但最好还是在出现 OutOfMemoryError 后重启程序。因为 OutOfMemoryError 可能会让程序处于不稳定的状态。由不稳定程序实例处理的请求可能会导致错误的结果。
示例:
-XX:OnOutOfMemoryError=/scripts/restart-myapp.sh
传递该参数时,JVM 将在抛出 OutOfMemoryError 时调用 “/scripts/restart-myapp.sh”。在该脚本中,您可编写代码来优雅地重启程序。
(3). -XX:+CrashOnOutOfMemoryError
传递此 JVM 参数时,JVM 将在抛出 OutOfMemoryError 时强制直接退出。除了推出之外,JVM 还会生成文本和二进制崩溃文件(如果启用了核心文件的话)。但就个人而言,我不建议配置该参数,因为我们应该始终以“优雅地退出”为目标。突然退出可能会危及正在进行的事务。
我运行了一个带有此“-XX:+CrashOnOutOfMemoryError”参数且会出现 OutOfMemoryError 的程序。可以看到,抛出 OutOfMemoryError 后 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
#
From the message, you could see hs_err_pid file to be generated in ‘C:\workspace\tier1app-svn\trunk\buggyapp\hs_err_pid26064.log’. hs_err_pid file contains information about the crash.您可使用 fastThread 等工具来分析 hs_err_pid 文件。但 hs_err_pid 中的大部分时间信息十分基础。不足以支撑 OutOfMemoryError 的故障排除工作。
(4). -XX:+ExitOnOutOfMemoryError
传递此 参数时,JVM 将在抛出 OutOfMemoryError 时强制直接退出。如果您想终止应用程序,则可传递该参数。但就个人而言,我不建议配置该参数,因为我们应该始终以“优雅地退出”为目标。突然退出可能会危及正在进行的事务。
我再次用同一个有内存泄漏问题的程序,在传递了“-XX:+ExitOnOutOfMemoryError” JVM 参数的情形下进行了运行。与“-XX:+CrashOnOutOfMemoryError”不同,该 JVM 参数没有生成任何文本/二进制文件。JVM 直接退出了。
Leave a Reply