私のプロジェクトを停止すると、Tomcatは次のように言います:
次の Web アプリケーションは停止 (リロード、アンデプロイ) されましたが、以前の実行のクラスがまだメモリにロードされているため、メモリ リークが発生しています (プロファイラーを使用して確認してください)。
どのクラスがメモリに残っているかはどこでわかりますか?
私を助けてください 。
私のプロジェクトを停止すると、Tomcatは次のように言います:
次の Web アプリケーションは停止 (リロード、アンデプロイ) されましたが、以前の実行のクラスがまだメモリにロードされているため、メモリ リークが発生しています (プロファイラーを使用して確認してください)。
どのクラスがメモリに残っているかはどこでわかりますか?
私を助けてください 。
実行jmap -histo
すると、ロードされたクラスが表示されます。
例えば:
jmap -histo[:live] <pid>
to connect to running process and print histogram of java object heap
if the "live" suboption is specified, only count live objects
Example: jmap -dump:live,format=b,file=heap.bin <pid>
もう 1 つの方法は、クラスローディングのデバッグ情報を有効にし、スクリプトを実行してロードされたままになっているものを検出することです。
これが発生すると、一般に、WebappClassLoader (Web アプリケーションのインスタンスのクラスをロードする役割を持つクラス ローダー) をメモリに "固定" する何かがメモリ内に存在します。Web アプリケーションを数回再ロードすると、再ロードを実行するたびに WebappClassLoader インスタンスの数が 1 ずつ増加することがわかります。これは通常、Tomcat でのリークではなく、Web アプリケーションのコードでの直接のリーク、使用しているライブラリでのリーク、または愚かなことを行ういくつかの特定の Java API 呼び出しによってトリガーされたリークです。
まず、http: //people.apache.org/~markt/presentations/2010-11-04-Memory-Leaks-60mins.pdfをお読みください。何が起こっているのかを正確に説明する優れた説明です。
次に、プロファイラーを使用して、WebappClassLoader によって読み込まれたオブジェクトへの参照を保持しているものを特定します。多くの場合、単に ServletContextListener を使用するだけで、Web アプリケーションが停止しているときにこれらの参照をクリーンアップできます。
第三に、使用しているライブラリからリークが発生していることが判明した場合は、そのことを知らせてください。JRE のクラスからのリークが見つかった場合は、JreMemoryLeakPreventionListener を使用するためのオプションを調べてください: http://tomcat.apache.org/tomcat-6.0-doc/config/listeners.html#JRE_Memory_Leak_Prevention_Listener_-_org.apache .catalina.core.JreMemoryLeakPreventionListener . 見つけたもののオプションがない場合は、Tomcat ユーザーのところに立ち寄って、足りないものをお知らせください。追加します。