ガーベッジフリーモードでは、Log4j2はLogEventオブジェクトを再利用します。同時に複数のスレッドが同じLogEventを変更しないようにするため、各スレッドには独自のLogEventがあります。これはThreadLocalで実装されています。
ThreadLocalsの重要なポイントは、明示的に削除されるかスレッドが終了するまでは、そこに置かれているものがそのまま残ります。 LogEventへの他の参照がない場合でも、ThreadLocalにはまだ参照があり、スレッドはGCのルートであるため、ガベージコレクションは行われません。
Webアプリケーションコンテナは、多くの場合、カスタムクラスローダーでWebアプリケーションをロードします。これにより、Webアプリケーションコンテナを再起動することなく、異なるバージョンのWebアプリケーションを停止して再読み込みすることができます。ただし、以前のバージョンのWebアプリケーション、そのクラス、およびカスタムクラスローダーを含むすべての関連クラスへの参照がまだガベージコレクションされていない場合、
これはいつ発生しますか? WebアプリケーションコンテナにWebアプリケーション間で共有されるスレッドプールがあり、Webアプリケーションの再読み込み時にフラッシュされないとき。プール内のスレッドには、LogEventオブジェクトと以前のバージョンのWebアプリケーションのクラスに対するThreadLocal参照が残っているため、このクラスはガベージコレクションできず、メモリリークが発生します。 Webアプリケーションがリロードされると
- スレッドプールは、Webアプリケーション
- の間で共有されていません。次の条件の両方に該当する場合は、Webアプリケーションではごみの無料ロギングを使用することができます
結論 そのスレッドプールもシャットダウンして再起動します
上記の両方が当てはまる場合は、Log4j2が危険な無駄なログを使用するように設定することができますメモリリークを引き起こします。もちろん、デューデリジェンスとテストをする必要があります。