Java向けの障害解析ツールHeapStatsをGlassFishに入れてみた

こちらで紹介されているJava向けの障害解析ツールHeapStatsが便利そうなので導入してみた。

 

環境はGlassFish3.1 + JDK7 + CentOS 6.3(32bit)

 

まずは、運用環境にrpmを使ってインストール.

wget http://icedtea.wildebeest.org/download/heapstats/heapstats-1.0.0/bin/agent/el6/i686/heapstats_agent-1.0.0-0.el6.i686.rpm
sudo rpm -ihv heapstats_agent-1.0.0-0.el6.i686.rpm

Wikiにも記載があるとおりrpmで入れた場合は/etc/heapstats/heapstats.confに設定ファイルができる。今回はログの出力先を${DOMAIN}/logsに変更したかったので下記のように修正

diff ./heapstats.conf /etc/heapstats/heapstats.conf
5,7c5,7
< file=../logs/heapstats_snapshot.dat
< heaplogfile=../logs/heapstats_log.csv
< archivefile=../logs/heapstats_analyze.zip
---
> file=heapstats_snapshot.dat
> heaplogfile=heapstats_log.csv
> archivefile=heapstats_analyze.zip

続いてGlassFishにHeapStatsの呼び出しを追加する。

管理コンソール等で「JVMの設定」  -> 「JVMオプション」 -> 「JVMオプションの追加」で下記のオプションを追加する。

-agentpath:/usr/lib/heapstats/libheapstats.so=/etc/heapstats/heapstats.conf

さて、これで仕込みはOKとGlassFishを再起動してみると...

立ち上がらないよ!

起動時に下記のようならエラーが出ていました。

[glassfish@webook glassfish]$ bin/asadmin start-domain ebooksearchDomain
Waiting for ebooksearchDomain to start .Error starting domain ebooksearchDomain.
The server exited prematurely with exit code 1.
Before it died, it produced the following output:

heapstats INFO: HeapStats 1.0.0
heapstats INFO: Supported processor features: None
Error occurred during initialization of VM
agent library failed to init: /usr/lib/heapstats/libheapstats.so
heapstats WARN: Failure search library on memory.
heapstats WARN: Failure getting symbol information.
heapstats CRIT: Getting low level infomation failed!

はて、なんだろ。とりあえずlibheapstats.soでシンボル情報が無いって言われてるみたい。

heapstatsのソースコードの関連しそうな部分を眺めてみると下記のようにun.boot.library.pathという、なんとなくOracleJVM(Sun JVM)に依存しそうな記述を発見。

2090 bool oopUtilInitialize(jvmtiEnv *jvmti) {
2091 
2092   /* Search symbol in libjvm. */
2093   char *libPath = NULL;
2094   jvmti->GetSystemProperty("sun.boot.library.path", &libPath);
2095   try{
2096     /* Create symbol finder instance. */
2097     symFinder = new TSymbolFinder();
2098     if(unlikely(!symFinder->loadLibrary(libPath))){
2099       throw 0;
2100     }

実はOpenJDKを使ってたんだけど、OpenJDKを利用しないといけない明確な理由も無いので、OracleJDK7に切り替え。再起動したところ無事起動ー。

ログが下記のように出力されてれば動作は成功。

[glassfish@webook glassfish]$ ls -1 logs/h*
logs/heapstats_log.csv
logs/heapstats_snapshot.dat

ちなみに現在出てるのはNomalモードのログ。障害時にはALLモードのログが出るみたい。明示的に出したいなら、SIGNAL2を下記のように飛ばせばOK。

kill -SIGUSR2 `ps ux|grep "glassfish.jar"|grep java|awk '{print $2}'`

これでheapstats_analyze130630190604.zipみたいな感じでログが出力されてればOK。

 

続いて解析の仕方。

出力されたheapstats_log.csvやheapstats_snapshot.datをローカルマシン等にコピーして

java -jar heapstats.jar

でクライアントを実行する。注意点として実行またはantのビルド時にjcommonとjfreechartが要求されること。

それぞれDLしてjarファイルをlib以下に置く必要がある。これは面倒だからivy + fat-jarに変更しておこうかなぁ。個人的にはmavenが楽で良いけど。

 

単にJMXで取る時と違って、メモリダンプも取れてるのはGood. 本番環境でもほぼ負荷がないということだし、とりあえず常に有効しておけばいいのかな。あと、クライアントでの解析の仕方が未だ慣れてないので、これは要勉強。

 

なんにしてもこの手のツールが整ってるのがJVM系の良いとこですね。

それでは、’Happy Hacking!

 

参考