Java/解析

Last-modified: 2013-03-18 (月) 17:28:35

トラブル解析方法

問題が発生した場合、以下の順に調査すると効率的かも。

  1. OSのCPU/メモリリソース確認
    → ボトルネックとなっているか確認
  2. GCログ解析
    → GCが多発していないか?ヒープ空きは十分か?
  3. 違う場合、CPU使用率を確認
    1. CPU使用率が高い場合
      → メソッドプロファイリング
    2. CPU使用率が高くない場合
      → スレッドダンプ解析 → ロック待ちでWaitしていないか?
      ロック待ちの対象は何か?スレッドプール、コネクションプール辺りが多い。
      プール初期値・最大値・使い方に問題がないか確認。



※ 通常JavaアプリでCPU使用率が高いことで問題になることは稀。
だいたいDBが遅い(SQLチューニング、DBロック待ち)

http://www.atmarkit.co.jp/fjava/rensai4/troublehacks01/troublehacks01_3.html

VisualVM

プロファイルをする場合は VisualVM が便利

取得できるもの

CPU使用率グラフ
GC状況
ヒープ使用率グラフ(New/Eden/Old/Perm別も)
スレッドダンプ
ヒープダンプ
スレッドの状況グラフ(スレッド数の時系列グラフ、個別スレッドごとの稼動状態時系列グラフ)
CPUホットスポット(CPU使用時間の多いメソッド・クラスの確認、それらの呼び出し箇所の確認)
スレッド別のホットスポット
ヒープ内容の確認(ローカル接続のみ)
ヒープダンプの差分からメモリリークオブジェクトの確認、呼び出し箇所の確認

解析手順

  1. 事前にアプリのJava起動オプションにJMX指定をしておく。
  1. 対象プログラムを起動。
  2. $JAVA_HOME/bin/jvisualvm.exeを起動。
  3. 左ツリーのリモートを右クリックから追加で、接続先ホストを指定。
  4. 追加したホストをさらに右クリックからJMX接続を追加。ポート番号に1で指定したJMXポートを指定。
  5. ダブルクリックで接続開始。
    これだけでCPU使用率・ヒープ使用量・スレッド状態のグラフ監視が可能。
  6. さらに「サンプラ」タブの「CPU」ボタンを押し、サンプリング開始させる。
    ヒープを解析したい場合は「メモリ」ボタンを。(ただしリモートでヒープ詳細は確認不可)
  7. 性能確認したい事象を発生させる。
  8. 事象が終わったところでサンプリングを終了させる。
  9. 必要に応じて事象前後等でスナップショットを取ると良い。

CPUサンプルではデフォルトで「セルフタイム」が選択されているが、これはThread.sleep()等の
時間も含まれるため、除外したい場合は「セルフタイム(CPU)」を選択すると良い。

その他解析ツール

GCログ
GCViewer
http://www.tagtraum.com/gcviewer.html
スレッドダンプ
Samurai
VisualVMでも可能
ヒープダンプ
MemoryAnalyzer(Eclipseプラグイン)
など

hprof:直接Windowsからネットワーク経由でプロファイラが使えない場合用

使えるならVisualVMを使ったほうが良い。

http://itpro.nikkeibp.co.jp/article/COLUMN/20061102/252525/

java -agentlib:hprof 実行クラス

で実行。結果は java.hprof.txt に出力される。

引数

デフォルトではヒープ情報のみ。
CPU利用率の高いものを取るには

-agentlib:hprof=cpu=samples

※ cpu=timesの方が正確になると思われるが、非常に遅いためsamplesを使う

jhat等のほかプログラムで開く場合には以下のようにバイナリフォーマットを指定する

-agentlib:hprof=format=b
詳細オプション
オプション機能デフォルト値
heap=dump/sites/allヒープのプロファイリングを行う。all
cpu=samples/times/oldCPU 時間のプロファイリングを行う。off
monitor=y/nモニターの競合のプロファイリングを行う。n
format=a/b出力形式。aはASCII形式、bはバイナリ形式。a
file=nameデータを出力するファイル名を指定する。java.hprof (ASCII の場合は .txt)
net=host:port指定した場合、プロファイリングデータをソケット経由で送信する。ファイル出力
depth=size出力スタックトレースの深さ。4
cutoff=value出力のカットオフポイント。
例えば0.2と指定した場合、ヒープ占有率または
CPU占有率が20%未満のデータは出力されない。
0.0001
lineno=y/nトレースに行番号を出力するか。y
thread=y/nトレースにスレッド番号を出力するか。n
doe=y/n終了時にダンプするかを指定する。y
取得結果
rankCPU時間の順位
selfCPU時間のパーセンテージ
accumCPU使用時間の累積パーセンテージ(上位rankのselfとの和)
countヒットしたサンプリングタイミング数(samples指定)、またはメソッドのコール回数(times指定)
trace対応するトレース番号