一般に、リークには複数のタイプがあり、それらは再デプロイ シナリオに適用されます。実稼働システムの場合、可能であれば再起動を実行するのが最善です。今日のアプリケーションでは非常に多くの異なるコンポーネントとライブラリが使用されているため、それらをすべて見つけることは非常に難しく、修正することはさらに困難です。特に。すべてのソース コードにアクセスできない場合。
- メモリリーク
- Thread および ThreadLocal リーク
- ClassLoader リーク
- システム リソースのリーク
- 接続リーク
ClassLoader のリークは、再デプロイ時に発生するものです。
それらはすべてによって引き起こされる可能性があります。本当に、私はすべてを意味します:
- タイマー:タイマーにはスレッドがあり、実行時に作成されたスレッドは、現在のコンテキスト クラス ローダー、つまり Tomcat の WebappClassloader を継承します。
- ThreadLocals: ThreadLocals はスレッドにバインドされます。アプリ サーバーはスレッド プールを使用します。ThreadLocal が Thread にバインドされ、その Thread がプールに返された場合、だれもそれを適切に remove() しなければ、ThreadLocal はそこにとどまります。非常に頻繁に発生し、見つけるのが非常に困難です (めったに使用されない Spring NamedThreadLocal を除いて、ThreadLocals には名前がありません)。ThreadLocal が WebappClassloader によってロードされたクラスを保持している場合、ClassLoader リークが発生します。
- キャッシュ:例: EhCache CacheManager
- リフレクション: JavaBeans Introspector (クラスまたはメソッドのキャッシュを保持するなど)
- JDBC ドライバー:いずれにせよ、それらはファイルに含まれるべきではありませ
.war
ん。静的レジストリによるリーク
- Commons-Logging LogFactory などの ClassLoaders をキャッシュする静的ライブラリ
Tomcat に固有の、私の経験は次のとおりです。
- 「クリーンな」ライブラリを備えた単純なアプリの場合、Tomcat で正常に動作します
- Tomcat は、WebappClassloader によってロードされたクラスをクリーンアップしようと非常に懸命に試みます。たとえば、Web アプリケーションがアンデプロイされると、クラスのすべての静的フィールドが null に設定されます。これにより、ロガーを使用するバックグラウンド ジョブなど、アンデプロイが行われている間にコードが実行されると、NullPointerExceptions が発生することがあります。
- Tomcat には、さらに多くのものをクリーンアップするリスナーがあります。それが呼ばれ
org.apache.catalina.core.JreMemoryLeakPreventionListener
、最近Tomcat 6.xに提出されました
エンタープライズ グレードの Java Web アプリケーションで発生する可能性のあるすべてのリークを「修正」しようとして、再デプロイのストレステストを行ったときにリークが発生した経験についてブログ記事を書きました。