JVM
JVM提供了很多处理 OutOfMemoryError
有用的参数。在本文中,我们介绍讲解一下这些参数。当你再遇到 OutOfMemoryError
进行故障排查时会很有帮助,这些参数如下:
下面我们来详细的看下每个参数的意义和用法。
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
了。
当发生内存溢出的时候,还可以让JVM调用任一个shell脚本。大多数时候,内存溢出并不会导致整个应用都 Crash
掉,但是,一旦发生OutOfMemoryError,最好重新启动应用程序。
因为 OutOfMemoryError
可能会使应用程序处于不稳定状态。一个不稳定的应用可能会提供错误的响应。使用举例:
-XX:OnOutOfMemoryError=/scripts/restart-myapp.sh
传递此参数时,每当抛出 OutOfMemoryError
时,JVM就会调用 /scripts/restart-myapp.sh
脚本。在此脚本中,您可以编写代码以优雅地方式重新启动应用程序。
如果给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
的原因进行定位。
传递此参数时,抛出 OutOfMemoryError
时,JVM将立即退出。如果您想终止应用程序,则可以传递此参数。但就我个人而言,我不希望配置该参数,因为我们应该始终以实现正常退出为目标。突然退出可能/将危害正在进行的事务。
我使用此 -XX:+ ExitOnOutOfMemoryError
JVM参数运行了相同的内存泄漏程序。与 -XX:+ CrashOnOutOfMemoryError
不同,此JVM参数不会生成任何文本/二进制文件,直接就退出了。
英文原文见: blog.gceasy.io
本文由nock 创作,采用 知识共享署名4.0 国际许可协议进行许可
本站文章除注明转载/出处外,均为本站原创或翻译,转载前请务必署名
最后编辑时间为: Dec 17, 2019 at 11:56 pm