原文はこちら。
The original article was written by Joakim Nordström (Principal Member of Technical Staff, JVM Sustaining Engineering group at Oracle).
https://inside.java/2021/04/30/failed-writing-core-dump/
JVMがクラッシュした際に生成されるhs_err
というHotSpotエラーファイルの調査をしてきました。よくあるエラーはコアダンプの書き込みに失敗する、というものです。

コアダンプ書き込みの失敗はしかしながらJVMをクラッシュさせるエラーではなく、コアダンプが書き込まれなかったことをJVMが通知しているのに過ぎません。
TL;DR コアダンプ書き込み失敗を解消したいだけならば、利用するための引数に直接飛べばよいのです。
Nota bene(注意) これはクラッシュを解決するのではありません。システムを埋め尽くす大きなファイル、つまりコアダンプが発生するだけです。
コアダンプ、もしくはWindowsにおけるMinidumpは、クラッシュしたプロセスのスナップショットです。例えて言えば、JVMがドライブ中の車だとして、突然、他の車やレンガの壁、態度の悪いドライバーなど、何かに衝突した場合を想像してみてください。保険会社が何が起こったのかを見て調べるために、JVMはクラッシュした場所の写真を撮ることができるのです。
OSによって、コアダンプの作成方法は異なります。Windowsでは、dbghelp.dll
というDLLにMiniDumpWriteDump
関数があり、JVMがこれを起動してコアダンプを生成します。POSIX系OS(Unix、Linux、macOS)では、abort()
関数を呼び出すことで、OSがコアダンプを生成します。
コア・ダンプの書き込みを有効にするJVM引数の-XX:+CreateCoredumpOnCrash
は、JDK9以上ではデフォルトで有効になっています。JDK 8の場合、この引数は-XX:+CreateMinidumpOnCrash
で、これはWindowsでのみ意味を持ちます。他のOSではこの引数は無視されます。
Failed to write core dump. Minidumps are not enabled by default on client versions of Windows
(コアダンプの書き出しに失敗しました。MinidumpはWindowsのクライアント版ではデフォルトで有効化されていません)
“Minidumps are not enabled by default on client versions of Windows”というメッセージのクライアントとは、Windows Serverに対するWindows Clientでの動作を意味しており、昔のHotSpotのCklient/Server VMの区別と混同しないでください。
Java Virtual Machine Technology
https://docs.oracle.com/javase/8/docs/technotes/guides/vm/index.html
Java仮想マシン・テクノロジ
https://docs.oracle.com/javase/jp/8/docs/technotes/guides/vm/index.html
Windowsクライアントでは、minidumpを書き込むようにJVMに指示しなければなりません。これはWindows自体とは関係ないので、Windowsの設定を変更する必要はありません(Windowsがクラッシュしたときの設定を有効にするという提案もありますが、ここでは適用されません)。minidumpファイル(かなり大きくなる可能性があります)がWindowsクライアントユーザーのディスクスペースを埋めてしまわないように、Windowsクライアント版で実行しているかどうかのチェックをJVMで明示的に行っています。しかし、Windows Serverでは、minidumpはデフォルトで有効になっています。
How to enable core dumps/minidumps
JDK 9 and above
任意のOSでJDK 9以後でコアダンプを有効化するには、Javaランチャーに -XX:+CreateCoredumpOnCrash
という引数を追加するだけです。
java -jar crasher.jar -XX:+CreateCoredumpOnCrash
コアダンプを無効にしたいなら、+を-にした引数に置き換えます。つまり、-XX:-CreateCoredumpOnCrash
を指定します。
JDK 8 on Windows
JDK 8が動作しているWindowsクライアント版では、 -XX:+CreateMinidumpOnCrash
を追加し、JVMクラッシュ時にminidumpを作成するようにします。
java -jar crasher.jar -XX:+CreateMinidumpOnCrash
Windows Serverでコアダンプを無効化したい場合は、+を-にします。つまり、-XX:-CreateMinidumpOnCrash
を引数に指定します。
POSIX系OSでJDK 8を使っている場合、コアダンプを無効化するJVMの引数はありません。その代わりに、OSレベルでコアダンプを無効化しなければなりません。
Unix, Linux, and macOS core dumps
POSIX系OSでは、コアダンプをOSレベルで無効化できます。このような場合、JVMは「Core dumps have been disabled(コアダンプが無効化されています)」と報告します。
Failed to write core dump. Core dumps have been disabled. To enable core dumping, try "ulimit -c unlimited" before starting Java again
(コアダンプの書き込みに失敗しました。コア・ダンプは無効になっています。コア・ダンプを有効にするには、Javaを再起動する前に、”ulimit -c unlimited “を実行してください。)
コアダンプのファイルサイズを制御するには、ulimit
コマンドと-c
引数を使用します。0
に設定するとコアダンプが無効になり、unlimited
に設定すると有効になります。ulimit -c unlimited
を実行すると、すべてのユーザーとすべてのプログラムでコアダンプが有効になります。ですから、まずOSレベルでコアダンプを有効にしてから、Javaプログラムを実行してください。そして、JDK9以上の場合は、-XX:+CreateCoredumpOnCrash
を追加する必要があることを覚えておいてください。
ulimit -c unlimited
java -jar crasher.jar -XX:+CreateCoredumpOnCrash
Summary of arguments
表にまとめると、JDK9以降では、コアダンプ/ミニダンプの扱いがより一貫していることがわかります。この一貫性は、JDK-8074354 “Make CreateMinidumpOnCrash a new name and available on all platforms” でJDK 9に追加されました。
Make CreateMinidumpOnCrash a new name and available on all platforms
https://bugs.openjdk.java.net/browse/JDK-8074354
下記の2表は、コアダンプの書き込みを有効にするための引数と、無効にするためのOSの要件をそれぞれまとめたものです。プラスとマイナスの記号に注意してください。
Enabling core dumps
この表では、デフォルトの動作をオーバーライドするために必要な設定を太字で示しています(つまり、Windowsクライアントでのみ、コアダンプを明示的に有効にする必要があります)。
OS | JDK 8での引数 | JDK 9以後での引数 | OSレベルの制御要否 |
---|---|---|---|
Windows client | -XX:+CreateMinidumpOnCrash | -XX:+CreateCoredumpOnCrash | N/A |
Windows server | -XX:+CreateMinidumpOnCrash | -XX:+CreateCoredumpOnCrash | N/A |
POSIX | N/A (常に有効) | -XX:+CreateCoredumpOnCrash | ulimit -c unlimited |
Disabling core dumps
2番目の表はコアダンプを無効化する方法を示したものです。太字はデフォルトの動作をオーバーライドするために必要な設定です。
OS | JDK 8 | JDK 9- | OSレベルの制御要否 |
---|---|---|---|
Windows client | -XX:-CreateMinidumpOnCrash | -XX:-CreateCoredumpOnCrash | N/A |
Windows server | -XX:-CreateMinidumpOnCrash | -XX:-CreateCoredumpOnCrash | N/A |
POSIX | N/A (常に有効) | -XX:-CreateCoredumpOnCrash | ulimit -c 0 |
What can be found in a core dump that can’t be found in the hs_err file? (hs_errファイルで見つけられずコアダンプで見つけられるものは?)
コアダンプはhs_err
テキストファイルの優れた追加機能です。コアダンプを調べるにはネイティブデバッガーが必要です。
生成されたhs_err
ファイルを見るだけで、極めて多くのことがわかります。
# Problematic frame:
# C [dump.dll+0x1006]
#
# Core dump will be written. Default location: D:\dumpster\hs_err_pid29804.mdmp
[...]
Native frames: (J=compiled Java code, j=interpreted, Vv=VM code, C=native code)
C [dump.dll+0x1006]
Java frames: (J=compiled Java code, j=interpreted, Vv=VM code)
j jaokim.dumpster.Divider.native_div_call(I)I+0
j jaokim.dumpster.Divider.do_div(I)I+2
j jaokim.dumpster.Dumpster.do_loops(I)V+16
j jaokim.dumpster.Dumpster.doTestcase(Ljava/lang/Integer;)V+5
j jaokim.dumpster.Dumpster.main([Ljava/lang/String;)V+58
v ~StubRoutines::call_stub
siginfo: EXCEPTION_INT_DIVIDE_BY_ZERO (0xc0000094)
クラッシュが発生した問題のフレームはネイティブコードのdump.dll
内であり、コアダンプが書き出されたことがわかります。
A crash happened outside the Java Virtual Machine
https://inside.java/2020/12/03/crash-outside-the-jvm/
このネイティブメソッドは、jaokim.dumpster.Divider.native_div_call
というJavaメソッドが呼び出していました。また、ある種のゼロ除算の例外(EXCEPTION_INT_DIVIDE_BY_ZERO
)と思われる現象も確認できます。しかし、dump.dll
のネイティブコードの詳細を知りたい場合、hs_err
ファイルではこれ以上の情報は得られません。
こうした失われた詳細情報を取得するには、ネイティブデバッガー(Windowsの場合はWinDbg)と生成されたコアダンプを使う必要があります。以下はクラッシュしている行
を直接示すWinDbgのスクリーンショットです。

正確なソースコードの行を知るためには、ネイティブデバッガーがデバッグシンボルを持っている必要があります。Windowsの場合、これらはdump.dll
をコンパイルした際に生成される.pdb
ファイルにあります。(.pdbファイルをコアダンプと同じディレクトリに置くとWinDbgが.pdb
ファイルを見つけることができます)。POSIX系OSでは、共有オブジェクト(dump.so
)をデバッグシンボルをONにしてコンパイルする必要があります。
Summary
JVMがクラッシュすると、クラッシュしたプロセスの詳細を含むコアダンプを書き出すことができます。コアダンプの書き出しが無効化されている場合、JVMはコアダンプ書き込みに失敗したことを知らせてくれます。しかし、これはJVMがクラッシュした実際の原因・理由とは無関係です。クラッシュの理由は、ほとんどの場合、hs_err
ファイルに記載されており、より複雑な詳細はコアダンプに記載されています。
通常、ほとんどの開発車はコアダンプを必要とはしませんが、その代わりにhs_err
ファイルに注目してどのコンポーネントが原因でクラッシュしたのかを最初に見つけるべきです。
このエントリで紹介したサンプルコードはGitHubにあります。
jaokim/inside-java-dumpster
https://github.com/jaokim/inside-java-dumpster