OutOfMemoryError相关JVM参数

in 互联网技术 with 0 comment  访问: 369 次

15765946651144.jpg
JVM提供了很多处理OutOfMemoryError有用的参数。在本文中,我们介绍讲解一下这些参数。当你再遇到OutOfMemoryError进行故障排查时会很有帮助,这些参数如下:

  1. -XX:+HeapDumpOnOutOfMemoryError -XX:HeapDumpPath
  2. -XX:OnOutOfMemoryError
  3. -XX:+ExitOnOutOfMemoryError
  4. -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会自动在指定目录下生成内存映像文件。

获取内存映像文件后,就可以使用HeapHeroEclipse 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:+ ExitOnOutOfMemoryErrorJVM参数运行了相同的内存泄漏程序。与-XX:+ CrashOnOutOfMemoryError不同,此JVM参数不会生成任何文本/二进制文件,直接就退出了。

英文原文见: blog.gceasy.io

WeZan
Responses