手持ちのコアファイルがない場合は、yasuenagさんのリポジトリからすぐに作れます!!
https://github.com/YaSuenag/garakuta/tree/master/NativeSEGV
Linuxではあらかじめulimit -c unlimited
してから実行してください。
デバッグ情報付きのOpenJDKビルドを使います。OpenJDKのソースをcloneして:
$ configure --enable-debug --with-native-debug-symbols=internal --disable-warnings-as-errors $ make images
です。
今回はjdk14 (https://hg.openjdk.java.net/jdk/jdk14/) をビルドしたものを使いました。buildディレクトリ以下にOpenJDKビルドができあがります。OpenJDKのビルドをしたことがない方には、オレ流のOpenJDKの開発環境(JJUG CCC 2019 Fall講演資料)を見ていただくとよいです(これもyasuenagさん…)。
$ jdk14/build/linux-x86_64-server-fastdebug/jdk/bin/java -version openjdk version "14-internal" 2020-03-17 OpenJDK Runtime Environment (fastdebug build 14-internal+0-adhoc.jyukutyo.jdk14) OpenJDK 64-Bit Server VM (fastdebug build 14-internal+0-adhoc.jyukutyo.jdk14, mixed mode)
このJDKにPATHを通しておきましょう。さて、jhsdbを立ち上げるわけですが、LinuxにはCLIしかないことも多いので、今回はjhsdbのリモート・デバッグ・サーバーを起動し、WindowsのjhsdbのGUIから接続して見ます。こんな感じのコマンドでjhsdbのサーバーを起動できます。
Examples: jhsdb debugd --pid 1234 or jhsdb debugd --core ./core.1234 --exe ./myexe
ではコアファイルとOpenJDKデバッグ版でjhsdbのリモート・デバッグ・サーバーを起動します。
$ jhsdb debugd --exe jdk14/build/linux-x86_64-server-fastdebug/jdk/bin/java --core ./core Attaching to core ./core from executable /home/jyukutyo/code/jdk14/build/linux-x86_64-server-fastdebug/jdk/bin/java and starting RMI services, please wait... Debugger attached and RMI services started.
started
と出力されれば起動しています。
WindowsでもjhsdbのGUIを起動します。jhsdb hsdb
を実行します。
$ jhsdb hsdb
File -> Connect to debug serverを選択し、マシン名を入力します。java.rmi.ConnectException
が出て接続できない場合は、WindowsのC:\Windows\System32\drivers\etc\hosts
やLinuxの/etc/hosts
を確認すると解決する可能性が高いです。私はWindowsのHyper-VでテキストモードのUbuntuを起動しており、内部ネットワークで固定のIPアドレスをUbuntuに割り当てていましたが、Windowsのhostsは設定していたもののLinuxのhostsを見落としており、最初接続できませんでした。
このとき、サーバーで指定したJDKのバージョンと、WindowsでGUIを起動したJDKのバージョンが異なると、上記の警告が出ます。また、バージョンの組み合わせによって例外が発生したり、GUIが使えない場合があります。そういう場合は、同じか少なくとも近いバージョンを使いましょう。
WARNING: Hotspot VM version 14-internal+0-adhoc.jyukutyo.jdk14 does not match with SA version 11.0.7+10. You may see unexpected results.
たとえば今回だとデバッグサーバは14、クライアントをAdoptOpenJDKの11で接続すると、次のような例外が出て使用できません。
無事接続できると、このような画面になります。
Tools -> Class Browserを選択します。java.lang.Object
を探してみましょう。
アドレスがわかりました。0x00000008000010c0
です。次に、Tools -> Inspectorを選択します。Address欄に0x00000008000010c0
を入れてEnterを押します。
HotSpot VMのシンボル名に関わるコード - Fight the Futureで話題にした、Symbolを見ることにします。
java.lang.Object
クラスのシンボルのアドレスがわかりました。0x00007ff2580650f0
です。これ以上の詳細を調べるには、GDBを使います。Linuxでデバッグサーバーを終了し、GDBを起動します。
$ gdb /home/jyukutyo/code/jdk14/build/linux-x86_64-server-fastdebug/jdk/bin/java core (gdb)
あとは、先ほど調べたアドレスを使うだけです。
(gdb) p ((Symbol*)0x00007ff2580650f0) -> _length_and_refcount $3 = 1114111 (gdb) p ((Symbol*)0x00007ff2580650f0) -> _body $4 = "ja" (gdb) p (char[])(((Symbol*)0x00007ff2580650f0) -> _body)[0]@16 $5 = "java/lang/Object"
シンボル名java/lang/Object
が見れました。もちろんbt
してバックトレースを見たりもできます。