Java Flight RecorderとMission Controlのまとめ

Java Flight Recorder(以下JFR)はいわゆるJavaプロセスのプロファイラ。
Java Mission Control(以下JMC)はJFRで取得したプロファイリングデータをGUIで見る事ができるビューア。
f:id:flick-flick:20140722012201p:plain

もともとはJRockitで搭載されていたのが, Java 7 Update 40以降で搭載されるようになった。
詳しくは
http://www.infoq.com/jp/news/2013/10/misson-control-flight-recorderHotSpot JVMで動作するMission ControlとFlight Recorder

で。



この機能は商用ライセンスのみになっているので、プロダクト用に利用する場合は商用ライセンス契約が必要。
ただし、JVMのオプションを指定することで利用できるようになっているのでお試しで利用することはできるみたい。


使い方は基本的には
http://docs.oracle.com/javase/8/docs/technotes/guides/jfr/toc.htmlTable of Contents

に全てが書いてあります。

起動方法

-XX:+UnlockCommercialFeatures -XX:+FlightRecorder

JVMオプションに指定してあげればOK.

プロファイリングの開始

$ java -XX:+UnlockCommercialFeatures -XX:+FlightRecorder -XX:StartFlightRecording=duration=60s,filename=myrecording.jfr MyApp

のようにプロセス起動時に開始するか

$ java -XX:+UnlockCommercialFeatures -XX:+FlightRecorder MyApp

で起動してから
jcmd(後述)でJFR.startコマンドを投げることによって開始される。

プロファイリング開始後の操作

jcmdコマンドを使ってjavaプロセスにコマンドを投げることによって、プロファイラに命令を送ることができる

#javaプロセスの確認
$ jcmd    
3857  ←プロファイリングしたいプロセス
20762 sun.tools.jcmd.JCmd

#このプロセスに投げることができるコマンド一覧の確認
$ jcmd 3857 help
3857:
The following commands are available:
JFR.stop
JFR.start
JFR.dump
JFR.check
VM.native_memory
VM.commercial_features
ManagementAgent.stop
ManagementAgent.start_local
ManagementAgent.start
Thread.print
GC.class_histogram
GC.heap_dump
GC.run_finalization
GC.run
VM.uptime
VM.flags
VM.system_properties
VM.command_line
VM.version
help

プロファイリングスタート

$ jcmd 3857 JFR.start
3857:
Started recording 1. No limit (duration/maxsize/maxage) in use.
Use JFR.dump recording=1 filename=FILEPATH to copy recording data to file.

recordingという番号がプロファイリング開始番号みたいな扱いらしい。
duration(期間)などの指定もオプションでできる

プロファイリングの状態の確認

$ jcmd 3857 JFR.check
Recording: recording=1 name="Recording 1" (running)

recording番号は1でプロファイリング実行中(runnning)というのが確認できる

プロファイリングデータのダンプ取得

$ jcmd 3857 JFR.dump filename="/tmp/myprofile.jfr" compress=true recording=1

filenameでダンプファイルのパスを指定して、zipでの圧縮がしたければcompress=trueを指定する。
recorindg番号を指定は必須

プロファイリングの終了

$ jcmd 3857 JFR.stop recording=1

これもrecorind番号は必須

JMCの起動

$ [JDK_PATH]/bin/jmc

で起動
JMX経由の情報も見ることができるが、今回はプロファイリングデータから読み込むのでメニューのファイルから開くで、ダンプした/tmp/myprofile.jfrを指定する。
f:id:flick-flick:20140722012301p:plain
時系列ごとによく使われいてるMethodやThreadの一覧、メモリの割り当て状況やIO(ファイルやネットワーク)の状況も全て解析できる。

プロファイリング対象の設定

デフォルトのプロファイリングの設定だとメモリの割り当て状況(Memory -> Allocations)やヒープのオブジェクト解析(Memory -> Object Statistics)がオフになっているので、有効にする。
(JMCでウィンドウ開いてもEvent type 'Allocation in new TRAB' is not enabled in this recordingとかEvent type 'Object Count' is not enabled in this recordingとか出て何もグラフに表示されない)

ちなみにTLABはThread Local Allocation Buffersの略。

$ls -l [JDK_PATH]/jre/lib/jfr
-rw-rw-r--  1 root  wheel  18574 Oct  8  2013 default.jfc
-rw-rw-r--  1 root  wheel  18531 Oct  8  2013 profile.jfc

これがプロファイリング用の設定ファイルらしい
とりあえずdefault.jrcをmyprofile.jfcとしてコピーして必要そうなところをfalse -> trueに書き換えて有効にする

$ diff default.jfc  myprofile.jfc
118c118
<       <flag name="class-loading-enabled" label="Class Loading">false</flag>
---
>       <flag name="class-loading-enabled" label="Class Loading">true</flag>
237c237
<       <setting name="enabled" control="heap-statistics-enabled">false</setting>
---
>       <setting name="enabled" control="heap-statistics-enabled">true</setting>
267c267
<       <setting name="enabled">false</setting>
---
>       <setting name="enabled">true</setting>
446c446
<       <setting name="enabled" control="allocation-profiling-enabled">false</setting>
---
>       <setting name="enabled" control="allocation-profiling-enabled">true</setting>
451c451
<       <setting name="enabled" control="allocation-profiling-enabled">false</setting>
---
>       <setting name="enabled" control="allocation-profiling-enabled">true</setting>

そしてプロファイリング開始時にこの設定を使ってプロファイリング開始するようにする

$ jcmd 3857 JFR.start settings=myprofile

これで先ほどと同じ通りにプロファイリングデータのダンプを取得してJMCに読み込ませれば、該当のプロファイリングが有効になってました。




参考:
Java Mission Control + Flight RecorderをGlassFish4で使ってみた - ブログなんだよもん
Running Java Flight Recorder
[http://hirt.se/blog/?p=370Creating Flight Recordings | Marcus Hirt
[http://hirt.se/blog/?p=381Allocation Profiling in Java Mission Control | Marcus Hirt