web-dev-qa-db-ja.com

Tomcatのアンデプロイメモリリークを回避する方法はありますか?

この質問は、Tomcatマネージャーの[リークを検索]ボタンをテストして次のような結果を得たことがある人を対象としています。

次のWebアプリケーションは停止(リロード、アンデプロイ)されましたが、以前の実行からのそれらのクラスはまだメモリにロードされているため、メモリリークが発生しています(プロファイラを使用して確認します)。
/leaky-app-name

これは、頻繁な再デプロイメントで頻繁に発生する「Perm Gen space」エラーと関係があると思います。

したがって、デプロイしたときにjconsoleに表示されるのは、ロードされたクラスが約2kから5kになることです。次に、アンデプロイでそれらを2kに戻す必要があると考えますが、それらは5kのままです。

また、次のJVMオプションを使用してみました。

-XX:+CMSClassUnloadingEnabled -XX:+UseConcMarkSweepGC -XX:+CMSPermGenSweepingEnabled

使用されたPerm Genスペースの量に非常に小さな低下が見られましたが、期待したものではなく、ロードされたクラスの数は減少していません。

それでは、Tomcatを構成する方法や、アンデプロイ時にアンロードするようにアプリを設計する方法はありますか?それとも、いくつかの主要なデバッグセッションの後でサーバーを再起動することに行き詰まっているのでしょうか。

Tomcatバージョン出力:

サーバーのバージョン:Apache Tomcat/6.0.29
サーバー構築:2010年7月19日1458
サーバー番号:6.0.0.29
OS名:Windows 7
OSバージョン:6.1
アーキテクチャ:x86
JVMバージョン:1.6.0_18-b07
JVMベンダー:Sun Microsystems Inc.

更新:

セリアスの回答のおかげで、もう少し掘り下げることにしました。CXF、Spring、JAXBのおかげで、アプリケーションに犯人がいると判断しました。

Javaアプリケーションをプロファイリングする方法を学んだ後、プロファイラをTomcatに向け、ヒープダンプとスナップショットを撮って、オブジェクトとクラスがメモリ内でどのように見えるかを確認しました。 CXF/JAXB(wsdl2Java)で生成されたクラスで使用されているXMLスキーマからの列挙は、アンデプロイ後に長引いていました。私のヒープダンプによると、オブジェクトはマップに関連付けられているようです。免責事項:オブジェクトの呼び出しツリーのプロファイリングとトレースは、Javaでは難しい場合があります。

また、サービスを呼び出すことさえせず、単にデプロイしてからアンデプロイしただけであることにも言及する必要があります。オブジェクト自体は、展開時にSpringから開始されたリフレクションを介して読み込まれるように見えました。春にCXFサービスを設定するための慣習に従っていたと思います。したがって、これがSpring/CXF、JAXB、またはリフレクションの障害かどうかは、100%わかりません。

補足として、問題のアプリケーションはSpring/CXFを使用するWebサービスであり、XMLはかなり複雑なスキーマです( [〜#〜] niem [〜#〜])の拡張 )。 。

54
waltwood

リークを引き起こさないようにしたい場合は、以下を実行する必要があります。

  • Webアプリケーションが、Webコンテナの共有ライブラリにあるJavaクラスを使用していないことを確認してください。共有ライブラリがある場合は、それらのライブラリのオブジェクトへの強い参照がないことを確認してください
  • 特にJava HashTableやSetsなどのオブジェクトでは)静的変数の使用を避けます。必要に応じて、removeを呼び出して、マップ、リストなどのオブジェクトを解放してください。

これもThreadLocalとMemoryLeaksに関する優れた記事です- http://blog.arendsen.net/index.php/2005/02/22/threadlocals-and-memory-leaks-revisited/

15
celias

Tomcat 7は、この領域で改善をもたらすことになっています。 Apache Tomcat 7の機能というタイトルのセクションを参照してください。これ以上のリークはありません!

彼らは、Webアプリケーションによって引き起こされる多くのメモリリークに対処できると信じています。残念ながら、それはまだベータ版です。

それ以外は、同じ経験をしていて解決策を見つけられなかったと言えます。展開には通常、後でTomcatを再起動する必要があります。犯人は誰なのかわかりません。私のWebアプリケーション、Tomcat、Hibernate、Tapestry、またはそれらのいくつかです。

6
Codo