Amazon CorrettoにおけるJMC・JFRの利用方法

前提

AWS Correttoで調べた内容にて記載
但し、他のOpenJDKにおいても殆ど同じ(はず)

概要

JVMのヒープの状況やスレッドの情報などを確認するためのツール
JMCとJFRの主な違いは以下の通り

JMC[JDK Mission Control]
  • GUIで確認するためのツール
  • リアルタイムで観測可能
  • JFRで取得した結果を可視化
JFR[JDK Flight Recorder]
  • 指定した期間イベントを記録するためのツール
  • 低負荷で観測することが可能

JMC、JFR共にJava7で提供されていたが、当時は本番利用はサブスクリプションが必要だった。
しかし、Oracle社がOpenJDKに寄贈してくれたので、Java11で本番でも無償利用可能になった。
また、Java8でも利用できる様にバックポート対応してくれた。
Amazon Corretto 8u262 と Corretto 11.0.8 が利用可能に
そのため、古いブログの記事とかでは本番ではライセンスが必要とか、
起動する際にUnlockCommercialFeaturesみたいなオプションが必要だったのは上記背景がある。

入手方法

JMC

Correttoには2021年6月時点では同梱されていない。
別途配布が行われているので、こちらから取得可能である。
(以下のページのDownloadに記載しているrelease pageから取得可能)
GitHub - corretto/corretto-jmc: A build of JDK Mission Control (JMC) by the Corretto team.

JFR

Correttoに同梱されている。

起動方法

JMC

JMC自身はjmc.exeを起動すれば良い。
JMC8.0.0.1 Windows版においては、ようこそ画面は文字化けして起動する。
(jmc.iniでfile.encodingをUTF8を指定したが変わらずであった)

f:id:yoneyore:20210606011959p:plain
閉じるとそれ以降は文字化けしていない

接続対象に関しては、ローカルとそれ以外で接続方法が異なる。

[ローカル]
勝手にJMCが検出してくれる。
(JDP[Java Discovery Protocol ]という機構で検出してくれている)

[ローカル以外]
JMXを有効化しておく必要がある。

(Javaプロセス起動時)

-Dcom.sun.management.jmxremote
-Dcom.sun.management.jmxremote.port=ポート番号
-Dcom.sun.management.jmxremote.rmi.port=ポート番号(上と同じで可)
-Dcom.sun.management.jmxremote.authenticat=false
-Dcom.sun.management.jmxremote.ssl=false

(Javaプロセス起動後)

jcmd Javaプロセス番号 ManagementAgent.start jmxremote.port=ポート番号 jmxremote.rmi.port=ポート番号 jmxremote.authenticate=false jmxremote.ssl=false

jcmdの上記オプションを忘れてしまった場合、以下の手順で確認できる。
1.jmc上で任意のプロセス(jmc自身でもOK)を選択
2.右クリックし、リモートJMXエージェントの制御を選択
3.以下の様なコンソールが現れる。
  オプションなど変更すると、一番下にjcmdでどの様なコマンドを発行するのか確認可能

f:id:yoneyore:20210606234635p:plain
なお、JMXの稼働状況確認や起動・停止することも可能
JFR

[jmc経由]
予めJMCでJFRを実行したいJavaプロセスと接続を行っておく必要がある。
その後、対象プロセスを選択した状態で右クリックを行い、フライト記録の開始を選択する。
するとフライト記録の開始というウィザードが表示される。
内容に従いながら設定することで記録が開始される。

[jcmd経由]
例) 1分録画する場合

jcmd Javaプロセス番号 JFR.start name=test maxage=1m filename=c:\temp\hogehoge.jfr

オプション詳細はJavaコマンドマニュアルのAdvanced Runtime Options for Java当たりから記載有
(但し、他のオプションも入り乱れている)

利用方法

他のサイトやYoutube上で沢山解説してくれている。

公式、英語だけど字幕&翻訳機能使えばだいたい追える
www.youtube.com
RedHatさんの公式ブログ
OpenJDK 8uでJDK Flight Recorderの入門 - 赤帽エンジニアブログ

P26~P39当たりに記載有
それ以外の部分もMTAやGC Viewerなど聞いたこと無いという人は是非見るべき資料
Javaの障害解析に関する道しるべ的良い資料
speakerdeck.com

その他

リモート接続がうまくいかない

どうもリモート接続するとうまくいかないケースがある。
原因としては、rmi接続する時の名前解決がうまくいかない場合に発生する模様である。
(IPv4で解決するところと、IPv6で解決するところが混在した場合に起きている?)
加えて、com.sun.management.jmxremote.local.onlyがtrueになっていた。
最適解では無いであろうが、以下の方法を行う事で接続できる様になった。

  • 接続対象のJava起動時に、 java.rmi.server.hostname=接続対象のIPv4アドレス を指定する
  • 接続対象のJavaJMX起動時に、 jmxremote.host=接続対象のIPv4アドレス を指定する
認証やSSLの設定を行いたい

Windowsのがうまく設定できないので、実現出来た時に纏める
Linuxの場合の対応方法
www.programmersought.com

jcmdで良く利用するコマンド
# JMXの起動(上記解説の通り、別途オプションが色々必要)
jcmd Javaプロセス番号 ManagementAgent.start
# JMXの状態確認
jcmd Javaプロセス番号 ManagementAgent.status
# JMXの停止
jcmd Javaプロセス番号 ManagementAgent.stop
# 起動引数の確認
jcmd Javaプロセス番号 VM.command_line
# system.propertyの値の確認
jcmd Javaプロセス番号 VM.system_properties
# VMフラグの値を出力(-allで全量出力)
jcmd Javaプロセス番号 VM.flags
# スレッドダンプ取得(-lで詳細出力)
jcmd Javaプロセス番号 Thread.print
# ヒープダンプ取得(-allでファントム参照も含める、引数無の場合はフルGC後取得)
jcmd Javaプロセス番号 GC.heap_dump filename=c:\temp\hogehoge.dump

詳しく知りたい場合は、JavaSE11のマニュアル jcmdユーティリティを参照すれば良い。

参考資料

JDK11のJMCのマニュアル、今は分かりにくい
JDK Mission Control | Oracle 日本
JDK7のJMCのマニュアル、古いけど日本語で読みたいなら今はこっち
Java Platform, Standard Edition Java Mission Control ユーザーガイド
JFRに関する解説を記載してくれている
目次 · 入門: JDK Flight Recoder
JFR Event Streamingについて
【NADP】JFR Event Streamingについて(デモ解説その1) | インサイト - Natic | 日商エレクトロニクス
トラブルシューティングについてどうやってしていけばいいのか丁寧に解説してくれている
youtu.be
古い本であるが、現代においても体系的に学習するのにとてもいい本

現場で使えるデバック&トラブルシュートが理解できる様になってから買った方がいいかも基礎が身についてないと感じたらこの本がお勧め
ストレージやCPUで遅くなる理由などがイメージしやすくなる