山下寛人オフィシャルブログ

オイシックス株式会社 執行役員 システム本部長 山下寛人の公式ブログです。

JBoss(Tomcat)がメモリを食いすぎるとき

以前からJBossがやたらとメモリを食う問題がありまして、

いろいろヒープメモリを分析したのですが特に自社開発部分で

メモリリークしている様子はなく長らく悩んでおりましたが

ようやく解決しました。

結論からいうとJBossの設定でした。JBossの中に入っている

Tomcatの部分で設定も同じなのでTomcatでも同じことが言えると

思います。

deploy/jboss-web.deployer/conf/web.xml

この中の<servlet>の中の<servlet-name>jsp</servlet-name>の

下のinit-paramがいくつかあります。

デフォルトではdevelopmentがtrueの状態です。

これをfalseにするため設定を追加します。

<init-param>
  <param-name>development</param-name>
  <param-value>false</param-value>
</init-param>

developmentをfalseにした場合、checkIntervalも設定しなければ

なりません。

<init-param>
  <param-name>checkInterval</param-name>
  <param-value>300</param-value>
</init-param>

以上でヒープメモリの使用量が激減しました。

以前はGCのログ出力で最大1G近く行っていましたが今はFull GC後で

200M前後です。

これはなぜかというと、developmentモードだとエラーが起こった時に

詳しいメッセージを出すために全部のJSPがメモリ上に保持されてしまう

らしいです。

http://blogs.atlassian.com/2007/04/4_more_days_in_a_leaky_boat/

This means that source of every JSP is held in memory to provide
detailed messages in the event of an error. If you have large JSPs
this will hurt. It looks like this accounts for 50MB+

とんでもないことです。

Memory Analyzer ToolでLeak Suspectsのレポートを見たりすると

JspServletがものすごくメモリを使っていることがわかります。


このJspServletの中をたどっていくとchar[]でJSPのソースが入って

いることが確認できます。

ちなみにMemory Analyzer Toolは無料なのにかなり便利です。

なおdevelopmentモードの場合はアクセスがあるたびにJSPが更新されるか

チェックして変更があったらすぐに反映されるのですが、falseにした

場合はcheckIntervalに設定した間隔でまとめてチェックするので

反映されるまでタイムラグが発生します。

この点注意が必要です。

またオイシックスではJSPの量が多いのでサーバーのLoad Averageがやや

上がったように思います。それでも0.1~0.2程度なのでそれほど問題は

ありませんでした。