Log4j 2.x を使用した Web アプリケーションの再配備を繰り返すと古いアプリケーションで使用していたメモリが解放されずに java.lang.OutOfMemoryError: Metaspace が発生しました。
(JDK 7 以前の場合は、java.lang.OutOfMemoryError: PermGen space となります)
原因と対処方法を教えてください。
再配備の繰り返しに伴う java.lang.OutOfMemoryError: Metaspace 発生についての一般的な話は以下の FAQ を参照してください。
【WebOTX Application Server】アプリケーションの再配備を繰り返すと OutOfMemoryError が発生する(OTX-FAQ-000874)
ここでは、Log4j 2.x を使用する際の注意点について説明します。
Log4j 2.x は、アプリケーション終了時にロギングに使用したリソースを解放するために、シャットダウンフックを登録します。
登録されたシャットダウンフックがアプリケーションのクラスローダを参照しているため、配備解除しても古いアプリケーションのクラスローダが GC 対象になりません。
その結果、クラスがアンロードされず Metaspace のメモリが解放されません。
シャットダウンフックとは、JVM 終了時に実行される処理 (未起動の java.lang.Thread) を登録しておく機能です。
しかし、Java EE アプリケーションサーバ上で動作する Web アプリケーションの場合は、JVM 終了時ではなく、アプリケーションの停止・配備解除時にリソースを解放する必要があり、シャットダウンフックの利用は適切ではありません。
Web アプリケーションで Log4j 2.x を使用する場合は、log4j-web の jar ファイルも WEB-INF/lib に含める必要があります。
これによって、シャットダウンフックが登録されなくなり、その代わりに Web アプリケーションの停止・配備解除時にリソースの解放処理が実行されるようになります。
Web アプリケーションが Servlet 3.0 以降に準拠している場合は、log4j-web の jar ファイルを追加するだけで十分ですが、Servlet 2.5 に準拠している場合は、サーブレットリスナー Log4jServletContextListener とサーブレットフィルター Log4jServletFilter を設定する必要があります。
Servlet のバージョンは Web アプリケーションに含まれる WEB-INF/web.xml の <web-app> 要素の version 属性で判断できます。なお、web.xml が存在しない場合は、Servlet 3.0 以降に準拠しています。
詳細は、Log4j 2.x の以下のドキュメントを参照してください。
Using Log4j 2 in Web Applications
https://logging.apache.org/log4j/2.x/manual/webapp.html【対象製品】Application Server
【確認済みのバージョン】V8以降
【確認済みのエディション】すべて
【確認済みの対象OS】すべて
【確認済みのJavaバージョン】すべて
【コンポーネント】配備
【カテゴリー】トラブルシューティング