Upgrade to Pro — share decks privately, control downloads, hide ads and more …

GraalVM Native Image 解析方法の紹介

GraalVM Native Image 解析方法の紹介

2023年11月11日(土)開催の JJUG CCC 2023 Fall で発表した内容の資料です。

More Decks by NTTドコモソリューションズ Java担当

Other Decks in Programming

Transcript

  1. Copyright ©︎ NTT COMWARE CORPORATION 2023 GraalVM Native Image 解析方法の紹介

    2023.11.11(Sat) JJUG CCC 2023 Fall NTTコムウェア株式会社 坂本統 坂本翔平
  2. Copyright ©︎ NTT COMWARE CORPORATION 2023 ◼ 所属 ◼ NTT

    コムウェア株式会社 ◼ 担当 ◼ 社内技術集約組織 Java 担当 ◼ Java 実行開発環境(JRE/JDK)専門チーム ◼ 主幹メンバ ◼ 坂本統(テックリード/OpenJDK Author) ◼ 坂本翔平(テックリード) ◼ 業務 ◼ Java システムの技術サポート ◼ JVM プロファイリング&トラブルシューティング ◼ OpenJDK クラッシュ解析 etc. ◼ Java 関連先端技術調査 ◼ GraalVM & Native Image の調査など スピーカー紹介 1 坂本統 坂本翔平
  3. Copyright ©︎ NTT COMWARE CORPORATION 2023 GraalVM ネイティブ・イメージの JVM 観点のトラブルシューティング方法を紹介

    昨今高性能でリッチな Java 実行環境である GraalVM※ が注目され、特にクラウド・ネイティブには Native Image 機能を利用して Java アプリケー ションを高速起動かつ低メモリ消費のネイティブ・イメージ(単独実行可能なバイナリファイル)に変換し活用することの検討が進んできている様に見える。 商用利用にはトラブルシューティングの方法の把握が必要だが、ネイティブ・イメージは従来の Java Virtual Machine(HotSpot VM など)とは異なる、 軽量な Substrate VM を使用しているため JVM 関連情報の取得方法や参照方法に差異がある。 弊社ではネイティブ・イメージの技術サポートの要望に備えてそのトラブルシューティングのノウハウを蓄積してきた。本セッションでは HotSpot VMと比較し た、ネイティブ・イメージのトラブルシューティングのための情報取得方法や解析方法、その情報の差分について紹介する。 本セッションで紹介する解析情報および検証環境は以下の通り。 本日のお話 2 解析情報 主な活用事例 バージョン情報 汎用的に利用 オプション情報 汎用的に利用 GC ログ 性能劣化 スレッドダンプ ハングアップ解析 ヒープダンプ メモリリーク フライトレコード アプリケーションプロファイリング エラーレポート プロセスクラッシュ コアダンプ プロセスクラッシュ 項目 ソフトウェア 備考 OS Linux(Ubuntu 22.04) Java 実行環境 GraalVM for JDK 21 Community Java アプリケーション Spring Petclinic Spring Boot 3.1.3 Native Build Tools 0.9.27 解析ツール Eclipse Memory Analyzer 1.12.0 VisualVM 2.1.7 GDB 12.1 10.2 以上推奨 解析情報一覧 検証環境 ※ GraalVM や Native Image 機能の詳細は公式ドキュメントをご確認ください。 <https://www.graalvm.org/>
  4. Copyright ©︎ NTT COMWARE CORPORATION 2023 バージョン情報は strings コマンドを使用して com.oracle.svm.core.VM

    にヒットする文字列を抽出することで取得できる。 バージョン情報 3 【バージョン情報の取得方法】strings コマンドでネイティブ・イメージの可読部分を表示 $ strings <native_image> | grep com.oracle.svm.core.VM com.oracle.svm.core.VMInspectionOptions_OptionDescriptors com.oracle.svm.core.VMInspectionOptions_OptionDescriptors com.oracle.svm.core.VMInspectionOptions com.oracle.svm.core.VM com.oracle.svm.core.VM=21+35 com.oracle.svm.core.VM.Java.Version=21 com.oracle.svm.core.VM.Target.Libraries=z|dl|pthread|rt com.oracle.svm.core.VM.Target.CCompiler=gcc|linux|x86_64|9.4.0 com.oracle.svm.core.VM.Target.LibC=com.oracle.svm.hosted.c.libc.HostedGLibC com.oracle.svm.core.VM.Target.Platform=org.graalvm.nativeimage.Platform$LINUX_AMD64 com.oracle.svm.core.VM.Target.StaticLibraries=liblibchelper.a|libnet.a|libjaas.a|libextn et.a|libnio.a|libmanagement_ext.a|libjava.a|libzip.a|libjvm.a strings コマンドを使用して com.oracle.svm.core.VM にヒットする文字列を抽出することで、ネイティブ・イメージのビルドに使用し た GraalVM のバージョンとベースの Java バージョンを取得できる。
  5. Copyright ©︎ NTT COMWARE CORPORATION 2023 実行中のネイティブ・イメージに指定しているオプション情報は ps コマンドで取得できる。 オプション情報

    4 【オプション情報の取得方法】ネイティブ・イメージのプロセス情報を ps コマンドで表示 $ ps aux | grep <native_image_name> user 1327261 2.5 0.3 1828040 213956 pts/0 Sl+ 17:26 0:00 ./target/spring-petclinic -XX:+PrintGC -XX:+PrintGCSummary user 1327379 0.0 0.0 10072 720 pts/2 S+ 17:26 0:00 grep --color=auto petclinic ps コマンドで実行中のネイティブ・イメージのプロセスを確認することで、指定したオプション情報を確認できる。 なおネイティブ・イメージの実行時に指定可能なオプションの一覧取得にはオプション -XX:PrintFlags= を用いる。 オプション一覧はオプション名と概要の記述がセットで出力される。 $ <native_image> -XX:PrintFlags= -XX:ActiveProcessorCount=-1 Overwrites the available number of processors provided by the OS. Any value <= 0 means using the processor count from the OS. -XX:±AutomaticReferenceHandling Determines if the reference handling is executed automatically or manually. Default: + (enabled). (以下略)
  6. Copyright ©︎ NTT COMWARE CORPORATION 2023 ネイティブ・イメージの実行オプションに GC ログオプションを指定することで GC

    ログが標準エラー出力される。 ネイティブ・イメージの実行オプションに指定できる GC ログオプションと GC ログ出力例を以下に示す。 GC ログ 5 ◼ GC ログ出力例 GC ログオプション 説明 -XX:±PrintGC 各 GC 実行後の GC 情報を表示 -XX:±VerboseGC 各 GC 実行前後の詳細な情報を表示 -XX:±PrintGCSummary アプリケーション終了後の GC 情報サマリを表示 -XX:±PrintGCTimes 各 GC のフェーズごとの実行時間を表示 -XX:±TraceHeapChunks GC 実行中のヒープチャンクを追跡 $ <native_image> -Xmx100m -Xms100m -Xmn30m - XX:+PrintGC -XX:+VerboseGC [0.075s] GC(0) Using Serial GC [0.075s] GC(0) Memory: 64026M [0.075s] GC(0) Heap policy: adaptive [0.075s] GC(0) Maximum young generation size: 30M [0.075s] GC(0) Maximum heap size: 100M [0.075s] GC(0) Minimum heap size: 100M [0.075s] GC(0) Aligned chunk size: 512K [0.075s] GC(0) Large array threshold: 128K [0.075s] GC(0) Collect on allocation [0.077s] GC(0) Eden: 37.85M->0.00M [0.077s] GC(0) Survivor: 0.00M->0.00M [0.077s] GC(0) Old: 0.00M->18.50M [0.077s] GC(0) Free: 0.00M->2.00M [0.077s] GC(0) Full GC (Collect on allocation) 37.85M->18.50M 1.220ms -XX:±PrintGC -XX:±VerboseGC ◼ GC ログオプション(Serial GC の例) ネイティブ・イメージにおける GC ログの注意点 指定できる GC ログオプションは GC 方式によって異なる点に注意。 またネイティブ・イメージで出力される GC ログは HotSpot VM のそれとは異なり 独自形式であるため、GCViewer のような既存のグラフ化ツールに対応していない 点に注意。
  7. Copyright ©︎ NTT COMWARE CORPORATION 2023 (参考)GC ログ その他オプション出力例 6

    $ <native_image> -Xmx100m -Xms100m -Xmn30m - XX:+PrintGC -XX:+PrintGCSummary [0.067s] GC(0) Full GC (Collect on allocation) 37.85M->18.50M 1.217ms [0.111s] GC(1) Full GC (Collect on allocation) 54.50M->36.50M 1.259ms [0.199s] GC(2) Full GC (Collect on allocation) 108.50M->72.50M 2.341ms (省略) GC summary Collected chunk bytes: 73.35M Collected object bytes: 72.57M Allocated chunk bytes: 146.85M Allocated object bytes: 144.59M Incremental GC count: 3 Incremental GC time: 0.001s Complete GC count: 3 Complete GC time: 0.004s GC time: 0.006s Run time: 0.200s GC load: 3% -XX:±PrintGC -XX:+PrintGCSummary $ <native_image> -Xmx100m -Xms100m -Xmn30m - XX:+VerboseGC -XX:+PrintGCTimes [0.053s] GC(0) Using Serial GC [0.053s] GC(0) Memory: 64026M [0.053s] GC(0) Heap policy: adaptive (省略) [GC nanoseconds: collection: 1324606 rootScan: 251582 cheneyScanFromRoots: 86487 cheneyScanFromDirtyRoots: 164704 promotePinnedObjects: 3798 blackenStackRoots: 55964 walkThreadLocals: 2487 blackenImageHeapRoots: 151415 blackenDirtyCardRoots: 164 scanGreyObjects: 35388 referenceObjects: 354 releaseSpaces: 1071486 GCLoad: 0%][0.055s] -XX:+PrintGCTimes -XX:±VerboseGC $ <native_image> -Xmx100m -Xms100m -Xmn30m - XX:+VerboseGC -XX:+TraceHeapChunks [0.053s] GC(0) Using Serial GC [0.053s] GC(0) Memory: 64026M [0.053s] GC(0) Heap policy: adaptive (省略) |0x00007f6a15a00000|0x00007f6a15a00830, 0x00007f6a15a03110, 0x00007f6a15a80000| 2%| O|A| |0x00007f6a0d87c000|0x00007f6a0d87c038, 0x00007f6a0ea7c048, 0x00007f6a0ea7c048|100%| O|U| |0x00007f6a14280000|0x00007f6a14280830, 0x00007f6a14280830, 0x00007f6a14300000| 0%| F|A| |0x00007f6a15100000|0x00007f6a15100830, 0x00007f6a15100830, 0x00007f6a15180000| 0%| F|A| |0x00007f6a14800000|0x00007f6a14800830, 0x00007f6a14800830, 0x00007f6a14880000| 0%| F|A| |0x00007f6a14700000|0x00007f6a14700830, 0x00007f6a14700830, 0x00007f6a14780000| 0%| F|A| -XX:+TraceHeapChunks ▪-XX:+PrintGCSummary の出力例 ▪-XX:+PrintGCTimes の出力例 ▪-XX:+TraceHeapChunks の出力例
  8. Copyright ©︎ NTT COMWARE CORPORATION 2023 スレッドダンプを取得するには、ネイティブ・イメージのビルド時にスレッドダンプ出力を有効化した上で QUIT シグナルを送信する。 スレッドダンプ

    7 【スレッドダンプ出力の有効化】ネイティブ・イメージのビルドオプションを指定 $ native-image -H:+DumpThreadStacksOnSignal <java_app_name> ビルドオプション -H:+DumpThreadStacksOnSignal を指定することで、スレッドダンプの出力を有効化できる。 なおこのオプションは Experimental であるためネイティブ・ビルド時には警告が表示される。 【スレッドダンプの取得方法】kill コマンドで QUIT シグナルを送信 実行中のネイティブ・イメージのプロセスに対して kill コマンドで QUIT シグナルを送信することでスレッドダンプが標準エラー出力される。 $ ps aux | grep <native_image_name> user 2828535 3.8 0.3 1940608 229184 pts/2 Sl+ 18:37 0:00 ./target/spring-petclinic user 2828692 0.0 0.0 7488 656 pts/1 S+ 18:38 0:00 grep --color=auto petclinic $ kill -QUIT 2828535 ネイティブ・イメージにおけるスレッドダンプの注意点 ネイティブ・イメージのスレッドダンプには Substrate VM 実装の Java コードも含まれる点に注意。
  9. Copyright ©︎ NTT COMWARE CORPORATION 2023 (参考)スレッドダンプ出力例 8 "http-nio-8080-exec-1" #69

    daemon thread=0x00007f28d0000b80 state=WAITING i SP 0x00007f28db9feb60 IP 0x000055dfbcc86755 size=112 com.oracle.svm.core.posix.headers.Pthread.pthread_cond_wait(Pthread.java) A SP 0x00007f28db9feb60 IP 0x000055dfbcc86755 size=112 com.oracle.svm.core.posix.thread.PosixParker.park0(PosixPlatformThreads.java:395) A SP 0x00007f28db9febd0 IP 0x000055dfbcc8653b size=48 com.oracle.svm.core.posix.thread.PosixParker.park(PosixPlatformThreads.java:375) A SP 0x00007f28db9fec00 IP 0x000055dfbcd03e46 size=64 com.oracle.svm.core.thread.PlatformThreads.parkCurrentPlatformOrCarrierThread(PlatformThreads.java:938) A SP 0x00007f28db9fec40 IP 0x000055dfbe180c89 size=48 jdk.internal.misc.Unsafe.park(Unsafe.java:56) A SP 0x00007f28db9fec70 IP 0x000055dfbddb5c80 size=16 java.util.concurrent.locks.LockSupport.park(LockSupport.java:371) (省略) A SP 0x00007f28db9fee30 IP 0x000055dfbd7bce19 size=32 java.lang.Thread.run(Thread.java:1583) A SP 0x00007f28db9fee50 IP 0x000055dfbcd0605e size=48 com.oracle.svm.core.thread.PlatformThreads.threadStartRoutine(PlatformThreads.java:833) A SP 0x00007f28db9fee80 IP 0x000055dfbcc87127 size=32 com.oracle.svm.core.posix.thread.PosixPlatformThreads.pthreadStartRoutine(PosixPlatformThreads.java:211) A SP 0x00007f28db9feea0 IP 0x000055dfbcbab390 size=96 com.oracle.svm.core.code.IsolateEnterStub.PosixPlatformThreads_pthreadStartRoutine_38d96cbc1a188a6051c29be1299a fe681d67942e(IsolateEnterStub.java:0) Substrate VM 実装の Java コード
  10. Copyright ©︎ NTT COMWARE CORPORATION 2023 ヒープダンプを取得するには、ネイティブ・イメージのビルド時にヒープダンプ出力を有効化した上で USR1 シグナルを送信する。 ヒープダンプ(1/3)

    9 【ヒープダンプ出力の有効化】ネイティブ・イメージのビルドオプションを指定 $ native-image --enable-monitoring=heapdump <java_app_name> ビルドオプション --enable-monitoring=heapdump を指定することで、ヒープダンプの出力を有効化できる。 【ヒープダンプの取得方法】kill コマンドで USR1 シグナルを送信 実行中のネイティブ・イメージのプロセスに対して kill コマンドで USR1 シグナルを送信することでヒープダンプがカレントディレクトリに 出力される。なおヒープダンプの取得時には Full GC が発生する。 $ ps aux | grep <native_image_name> user 1355542 3.3 0.3 1942704 231136 pts/2 Sl+ 11:00 0:00 ./target/spring-petclinic user 1355812 0.0 0.0 7488 724 pts/1 S+ 11:00 0:00 grep --color=auto petclinic $ kill -USR1 1355542 【ヒープダンプ出力先の指定方法】ネイティブ・イメージ実行時にオプションを指定 ネイティブ・イメージ実行時にオプション -XX:HeapDumpPath= を指定することでヒープダンプの出力先を設定できる。
  11. Copyright ©︎ NTT COMWARE CORPORATION 2023 ネイティブ・イメージ実行時にオプションを指定することで OutOfMemoryError 発生時にもヒープダンプを出力できる。 ヒープダンプ(2/3)

    10 【OOME 発生時におけるヒープダンプの取得方法】ネイティブ・イメージ実行時にオプションを指定 ネイティブ・イメージ実行時にオプション -XX:+HeapDumpOnOutOfMemoryError を指定することで、 OutOfMemoryError 発生時にヒープダンプが出力される。 $ ./outofmemoryerror -Xmx100m -Xms100m -Xmn30m -XX:+HeapDumpOnOutOfMemoryError Dumping heap to svm-heapdump-2977021-OOME.hprof ... Heap dump file created [102395861 bytes in 0.122 secs] Exception in thread "main" java.lang.OutOfMemoryError: Array allocation too large. (以下略) -XX:+HeapDumpOnOutOfMemoryError 使用時の注意点 ビルドオプション --enable-monitoring=heapdump を指定していないと本オプションが使用できない点に注意。 また本オプションは GraalVM for JDK 21(2023/09 リリース)から追加されたため、それ以前のリリースでは使用できない。
  12. Copyright ©︎ NTT COMWARE CORPORATION 2023 ◼ OOME を意図的に発生させ取得したヒープダンプを MAT

    で参照した画面例 ネイティブ・イメージから生成されたヒープダンプは Substrate VM 実装の Java コードや固有の byte 情報を含む。 ヒープダンプ(3/3) 11 ※ Eclipse Memory Analyzer(MAT): https://eclipse.dev/mat/ 専用ツールによるヒープダンプの解析 ヒープダンプの解析には HotSpot VM と同様に専用ツール Eclipse Memory Analyzer (MAT)※ が使用できる。 ネイティブ・イメージから生成されたヒープダンプを MAT で参照した場合、 Substrate VM 実装の Java コードや ネイティブアプリケーション固有の byte 情報も出力される。 OOME の原因 ネイティブ・イメージ 固有の byte 情報 Substrate VM 実装の Java コード
  13. Copyright ©︎ NTT COMWARE CORPORATION 2023 ネイティブ・イメージはデフォルトで JDK Flight Recorder

    機能を含まない。 ビルドオプション --enable-monitoring=jfr を指定することで JDK Flight Recorder 機能を追加できる。 フライトレコード(1/3) 12 $ native-image –enable-monitoring=jfr <java_app_name> 【JDK Flight Recorder 機能の有効化】 ネイティブ・イメージのビルドオプションに JFR 機能追加設定を指定 あらかじめネイティブ・イメージのビルド時に JDK Flight Recorder 機能を追加するオプション指定が必要。 ※ すべての解析機能を有効化する –enable-monitoring=all でも可
  14. Copyright ©︎ NTT COMWARE CORPORATION 2023 フライトレコード(2/3) 実行オプション –XX:StartFlightRecording= を指定することでフライトレコードの記録を開始できる。(HotSpot

    VM と同じ) アプリケーション停止時にカレントディレクトリもしくは filename で指定したパスにフライトレコードが出力される。 ※ -XX:+FlightRecorder は不要 ※ jcmd 操作(JFR.xxx サブコマンド)は未対応のためネイティブ・イメージの実行中に JFR 機能を操作できない ネイティブ・イメージから取得したフライトレコードは既存ツール(jfr/VisualVM/JDK Mission Control)で参照できる。 ※GraalVM for JDK 21 から gu が同梱されなくなったため VisualVM※ は個別に取得すること フライトレコードの記録開始オプションと、フライトレコードの可視化ツールは HotSpot VM と同じものが使用できる。 13 【フライトレコードの取得方法】 ネイティブ・イメージ実行時にフライトレコードの記録を開始するオプションを指定 $ <native_image> –XX:StartFlightRecording=settings=default,filename=<filename>… 【フライトレコードの参照方法】 専用ツールで参照 ※ VisualVM <https://visualvm.github.io/index.html>
  15. Copyright ©︎ NTT COMWARE CORPORATION 2023 フライトレコード(3/3) 14 JFR イベント

    VisualVM メニュー 情報の説明 備考 jdk.ThreadDump Overview – Thread dump スレッドダンプ jdk.CPULoad Monitor - CPU usage/Environment - CPU utilization CPU 使用量 jdk.MetaspaceSummary Monitor – Metaspace usage Metaspace 使用量 jdk.FileRead jdk.FileWrite File IO ファイル I/O jdk.SocketRead jdk.SocketWrite Socket IO ソケット I/O jdk.JavaErrorThrow jdk.JavaExceptionThrow Exceptions エラーおよび例外一覧 jdk.GCConfiguration jdk.GCHeapConfiguration jdk.YoungGenerationConfiguration jdk.GCSurvivorConfiguration jdk.GCTLABConfiguration GC – GC configuration GC – Heap configuration GC – Young Generation configuration GC – Survivor configuration GC – TLAB configuration 各種 GC 関連の設定値 jdk.ObjectCount Sampler - Heap histogram 各オブジェクトの数 #7402 で実装リクエスト中 jdk.ThreadAllocationStatistics Sampler - Per Thread Allocation スレッド割当統計 #7263 で JDK 22 にマージ jdk.CPUInformation Environment - CPU details CPU 情報 jdk.NetworkUtilization Environment - Network utilization ネットワーク使用量 jdk.SystemProcess Environment - System processes ホストで実行中のプロセス一覧 一部の JFR イベントが未実装のため、現在(GraalVM for JDK 21)は全ての情報を収集できない。 ※ 未実装の JFR イベントは Graal VM のイシュー #5410 で実装継続中。 ▪ 未実装 JFR イベント例(VisualVM で可視化可能な項目のうち未実装なもの)
  16. Copyright ©︎ NTT COMWARE CORPORATION 2023 (参考)VisualVM のフライトレコード表示例(1/4) 15 Monitor

    タブメニュー Overview タブメニュー 表示できない項目 ◼ JFR イベント未実装につき表示できない項目 ◼ Overview:スレッドダンプ ◼ Monitor:CPU 使用量グラフ/Metaspace 使用量グラフ
  17. Copyright ©︎ NTT COMWARE CORPORATION 2023 ◼ JFR イベント未実装につき表示できない項目 ◼

    File IO:すべて ◼ Socket IO:すべて ◼ Exceptions:すべて (参考)VisualVM のフライトレコード表示例(2/4) 16 File IO タブメニュー Socket IO タブメニュー Exceptions タブメニュー 表示できない項目
  18. Copyright ©︎ NTT COMWARE CORPORATION 2023 ◼ JFR イベント未実装につき表示できない項目 ◼

    GC:各種 GC 関連の設定値 ◼ Sampler(Memory):ヒープヒストグラム/スレッドごとのメモリ割当量 ◼ 新バージョンで実装済み (参考)VisualVM のフライトレコード表示例(3/4) 17 Sampler タブメニュー(Memory) GC タブメニュー 表示できない項目
  19. Copyright ©︎ NTT COMWARE CORPORATION 2023 ◼ JFR イベント未実装につき表示できない項目 ◼

    Environment:CPU 使用量グラフ/NW 使用量グラフ/ CPU 情報/NW 情報/システムプロセス一覧 (参考)VisualVM のフライトレコード表示例(4/4) 18 Environment タブメニュー 表示できない項目
  20. Copyright ©︎ NTT COMWARE CORPORATION 2023 エラーレポート(1/2) 19 ▪Substrate VM

    の Segmentation Fault エラーレポート出力例(先頭部分抜粋) ▪HotSpot VM の SEGV エラーレポート(hs_err)出力例(先頭部分抜粋) Substrate VM は Segmentation Fault 発生時に独自形式のエラーレポートを標準エラー出力する。 【エラーレポートの取得方法】 Segmentation Fault 発生時に標準エラー出力をキャッチ Substrate VM の Segfault ハンドラがクラッシュ発生時にエラーレポートを標準エラー出力(≠ファイル出力)する。 # A fatal error has been detected by the Java Runtime Environment: # # SIGSEGV (0xb) at pc=0x00007fc3abca5cd5 (sent by kill), pid=1082105, tid=1082105 [ [ SubstrateSegfaultHandler caught a segfault in thread 0x00005627f6d23800 ] ] siginfo: si_signo: 11, si_code: 0, si_addr: 0x000003e800000323 (heapBase - 135835956018397) 【エラーレポートの差分】 Segmentation Fault 独自形式の内容が出力 エラーレポートの内容は HotSpot VM の hs_err とは異なる独自形式の内容が出力される。
  21. Copyright ©︎ NTT COMWARE CORPORATION 2023 Segfault ハンドラ機能を無効するとクラッシュ時にコアダンプが出力される。 エラーレポート(2/2) 20

    【コアダンプの取得方法】 Segfault ハンドラ機能を無効化 ネイティブ・イメージのビルドオプション –R:-InstallSegfaultHandler か、実行オプション -XX:-InstallSegfaultHandler を 指定すると Segfault ハンドラを無効化できる。 Segfault ハンドラが無効されるとクラッシュ時にエラーレポートが出力されず、代わりにコアダンプが出力されるようになる。 ※クラッシュのコアダンプの出力は OS の機能に依存するため、出力されない場合はリソース制限設定(ulimit -c)と出力場所( core pattern)を確認すること ▪コアダンプ出力時のログ例(Segfault ハンドラ無効時) $ <native_image> –XX:-InstallSegfaultHandler Segmentation fault (core dumped)
  22. Copyright ©︎ NTT COMWARE CORPORATION 2023 (参考)エラーレポート表示項目一覧 21 項目名(原文) 概要

    SubstrateSegfaultHandler caught a segfault in thread… シグナルハンドラがキャッチしたシグナル情報&発生スレッド General purpose register values レジスタ値一覧 Printing instructions インストラクション一覧 Top of stack スタックのトップアドレス一覧 VM thread locals for the failing thread 問題発生スレッドの VM スレッドローカル一覧 Java frame anchors for the failing thread 問題発生スレッドの Java フレームアンカー(アドレス) Stacktrace for the failing thread 問題発生スレッドの Threads スレッド一覧 The 30 most recent VM operation status changes 直近30個の VM オペレーションログ VM mutexes VM ミューテックス一覧 General information 一般情報 Command line アプリケーションのコマンドライン引数 Heap settings and statistics ヒープ設定と統計 Heap usage ヒープ使用量 Native image heap boundaries ネイティブ・イメージのヒープ境界 Heap chunks ヒープチャンク
  23. Copyright ©︎ NTT COMWARE CORPORATION 2023 コアダンプ(1/3) 22 【デバッグ情報の生成】 ネイティブ・イメージのビルドオプションにデバッグ情報生成設定を指定

    コアダンプの解析にはそのダンプ元アプリケーション(ここではネイティブ・イメージ)のデバッグ情報が必要となる。 Java コンパイルおよびネイティブ・イメージのビルドの際に –g オプションを指定することで、デバッグ情報が生成される。 完全なデバッグ情報を生成するためにネイティブ・イメージの最適化レベルを指定する –O0 (最適化無効)の指定も推奨される。 あらかじめネイティブ・イメージのビルド時にデバッグ情報を生成するオプション –g を指定する。 $ javac –g App.java $ native-image –g –O0 App デバッグ情報はデバッグインフォ(native_image.debug)とデバッグソース(sources)の2つからなり、ネイティブ・イメージのビ ルド時に –g を指定するとこれらのデバッグ情報のファイル一式が生成される。 Produced artifacts: /path/to/build/home/app (executable) /path/to/build/home/app.debug (debug_info) /path/to/build/home/sources (debug_info) ▪ネイティブ・イメージのビルドログ抜粋(生成されたアーティファクト一覧)
  24. Copyright ©︎ NTT COMWARE CORPORATION 2023 コアダンプ(2/3) 23 コアダンプはクラッシュ時に OS

    の機能で出力されるか、実行中のプロセスに対し gcore コマンドを使用することで取得できる。 実行中のネイティブ・イメージのコアダンプを取得するには gcore コマンドを実行する。 【コアダンプの取得】 任意のタイミングで取得する場合は gcore コマンドを実行 $ sudo gcore <native_image_pid>
  25. Copyright ©︎ NTT COMWARE CORPORATION 2023 コアダンプ(3/3) 24 ネイティブ・イメージは Java

    コードを C++ 変換して生成された実行ファイルであるため GDB で参照できる。 ネイティブ・イメージにはユーザが認識可能な文字列等が含まれいらずそのままでは内容を読み取ることができない。デバッグ情報(デバッ グインフォとデバッグソース)があることで GDB がコアダンプ内容と関数や変数、ソースコードなどの文字列を紐づけることができ、ユーザが 内容を読み取りできる。なお GDB はカレントディレクトリのデバッグ情報を自動参照するため指定不要。(任意の場所指定も可能) GDB にネイティブ・イメージとコアダンプ、デバッグ情報を読み込ませることでバックトレースや変数値を参照できる。 【コアダンプの参照】 GDB でネイティブ・イメージとコアダンプ、デバッグ情報を読み込む $ gdb <native_image> <coredump> (gdb) bt #0 0x00007fd01dc937d1 in pthread_cond_timedwait@@GLIBC_2.3.2 () from /lib/x86_64-linux-gnu/libpthread.so.0 #1 0x00005612786a5a45 in com.oracle.svm.core.posix.headers.Pthread::pthread_cond_timedwait(com.ora cle.svm.core.posix.headers.Pthread$pthread_cond_t, com.oracle.svm.core.posix.headers.Pthread$pthread_mutex_t, com.oracle.svm.core.posix.headers.Time$timespec) (__0=<optimized out>, __1=<optimized out>, __2=<optimized out>) … 省略 (gdb) bt #0 0x00007fd01dc937d1 in pthread_cond_timedwait@@GLIBC_2.3.2 () from /lib/x86_64-linux-gnu/libpthread.so.0 #1 0x00005612786a5a45 in ?? () #2 0x00007ffcb857bb90 in ?? () #3 0x00005612786a5a32 in ?? () #4 0x00007ffcb857bbb0 in ?? () #5 0x0000000000000000 in ?? () ▪GDB バックトレース表示例(デバッグ情報あり) ▪GDB バックトレース表示例(デバッグ情報なし) ▪GDBでコアダンプを開くコマンド
  26. Copyright ©︎ NTT COMWARE CORPORATION 2023 ◼ 利用可能な機能 ◼ Java

    ソースコードの表示 ◼ ブレークポイント設定(ファイル/行/メソッド名) ◼ ステップ実行 ◼ バックトレース表示 ※インライン コードの詳細は不可 ◼ プリミティブ値の表示 ◼ Java オブジェクト(構造体表現)の表示 ◼ Java オブジェクトのキャストと表示 ◼ パス式を使用したオブジェクトへのアクセス ◼ メソッドおよび静的フィールドデータの名前による参照 ◼ パラメータおよびローカル変数にバインドされた値の名前による参照 (参考)GDB によるネイティブ・イメージのデバッグで利用可能な機能 25 (gdb) f 8 #8 java.lang.Thread::sleep(long) (millis=10000000) at java/lang/Thread.java:509 509 sleep0(nanos); (gdb) list ★ Thread.sleep() ソースコード(.java)の表示 504 ThreadSleepEvent event = beforeSleep(nanos); 505 try { 506 if (currentThread() instanceof VirtualThread vthread) { 507 vthread.sleepNanos(nanos); 508 } else { 509 sleep0(nanos); 510 } 511 } finally { 512 afterSleep(event); 513 } (gdb) p nanos $2 = 10000000000000 ★プリミティブ値の表示 ▪ Thread.sleep(long) のソース表示とプリミティブ値の参照例 詳細にデバッグするには Java オブジェクトを C++ の構造体として表現されていることを考慮して複雑な手順を踏む必要がある。詳細は以下のドキュメントを参照すること。 Debug Native Executables with GDB <https://www.graalvm.org/jdk21/reference-manual/native-image/guides/debug-native-image-process/> GDB では Java コードを扱っている様にネイティブ・イメージをデバッグできる。
  27. Copyright ©︎ NTT COMWARE CORPORATION 2023 まとめ 26 情報種別 取得可否

    必要なネイティブ・イメージのビルドオプション 取得方法 出力形式 解析ツール バージョン情報 〇 - $ strings <native_image> | ¥ grep “com.oracle.svm.core.VM” stdout - オプション情報 〇 - $ ps aux | grep <native_image_name> stdout - GC ログ (Serial GC) 〇 - $ <native_image> -XX:+PrintGC -XX:+VerboseGC ¥ -XX:+PrintGCSummary -XX:+PrintGCTimes ¥ -XX:+TraceHeapChunks stderr - スレッドダンプ 〇 -H:+DumpThreadStacksOnSignal $ kill -QUIT <native_image_pid> stderr - ヒープダンプ 〇 --enable-monitoring=heapdump $ <native_image> ¥ -XX:+HeapDumpOnOutOfMemoryError or $ kill -USR1 <native_image_pid> file (.hprof) VisualVM Eclipse Memory Analyzer フライトレコード △ (一部) --enable-monitoring=jfr $ <native_image> -XX:StartFlightRecording=… file (.jfr) jfr VisualVM JDK Mission Control エラーレポート 〇 - Substrate VM による出力 stderr - コアダンプ 〇 -g(デバッグ情報追加) OS 機能による出力 or $ sudo gcore <native_image_pid> file (core) GDB ※ 本一覧は GraalVM for JDK 21 Community に基づいた調査結果で、将来的なバージョンでは取得方法や各種オプションが変更になる可能性があることに注意。 GraalVM for JDK 21 以降ではフライトレコードの一部を除いて多くの情報を収集・解析可能