Tomcat のどのクラスがメモリリークしているかを確認したい時があります。
例えば、fullGC されているのに全然ヒープ使用量が減らない、ソースコードを読んでも検討がつかない
何かキッカケだけでも欲しい!などなど。
どのクラスが現在どれだけのインスタンスが存在していて、
どれだけのメモリを使っているのかを確認するには以下の様な手順で
ヒープの統計情報を取得することで可能になります。
以下は Amazon Web Services(AWS) の EC2 に Tomcat 7 をインストールしている前提です。
##準備
-
/etc/tomcat7/tomcat7.conf を編集する
(バックアップを取るのを忘れずに・・・)sudo vi /etc/tomcat7/tomcat7.conf
CATALINA_TMPDIRの下あたりに以下を追加
CATALINA_OPTS="-XX:+PrintClassHistogram"
-
再起動する
sudo service tomcat7 restart
##ヒープの統計情報を取得
-
Tomcat を起動している Javaプロセスに SIGQUIT を送信する
ps -ef | grep java | grep -v grep | awk '{print $2}' | xargs sudo kill -3
-
ログにヒープの統計情報が出力されます
tail -f /var/log/tomcat7/catalina.out
ログにはこんな感じで出力されます↓
num #instances #bytes class name
----------------------------------------------
1: 25100 3988192 <constMethodKlass>
2: 25100 3222400 <methodKlass>
3: 2091 2768360 <constantPoolKlass>
4: 21482 2353672 [C
5: 1813 1515712 <constantPoolCacheKlass>
6: 2091 1437248 <instanceKlassKlass>
7: 5346 860552 [B
8: 622 550584 [I
9: 21167 508008 java.lang.String
10: 4038 323040 java.lang.reflect.Method
11: 2339 283336 java.lang.Class
12: 8826 282432 java.util.HashMap$Entry
13: 456 230624 <methodDataKlass>
14: 3337 203528 [S
15: 3339 189808 [[I
16: 231 121968 <objArrayKlassKlass>
17: 2200 110024 [Ljava.lang.Object;
18: 533 103880 [Ljava.util.HashMap$Entry;
19: 2168 69376 java.util.concurrent.ConcurrentHashMap$HashEntry
20: 2989 62872 [Ljava.lang.Class;
21: 1306 52240 java.util.LinkedHashMap$Entry
22: 1418 45376 java.util.Hashtable$Entry
23: 909 43632 java.util.HashMap
(以下 延々と続くので省略)
※ 徐々にヒープ使用量が増えていくのでアワリーで統計取りたいなんて場合は、
cron に SIGQUIT コマンドを送信するように設定しておけば良いです