2

Web アプリケーションでメモリ リークを検出しようとしています。

  • クラッシュ時のアプリのヒープ ダンプを取得します。
  • Eclipse MAT を使用してダンプを解析します。

解析からの照合された情報は、次の 2 つの結論につながります -

  1. より多くのメモリを占有するオブジェクトには GC ルートがありません。基本的に、GC が発生するたびに、それらはクリーンアップされます。
  2. GC ルートの下にあるオブジェクトが占有するメモリは大幅に少なくなります。したがって、これらはメモリ リーク (?) の根本的な原因ではない可能性があります。

では、これはリークが発生していないことを意味しますか? メモリ不足エラーのためにクラッシュが発生しますか?

編集:環境情報の追加

  • Tomcat 6 で Java Web アプリケーションを実行しています。
  • webapp は openreports (レポート ツール) に基づいています。

最大のオブジェクトの着信参照リストを追加 -

http://imgur.com/lYrju

ここで、ハッシュ マップの各インスタンスには、GC で収集されていない com.opensymphony.xwork2 からの参照があります。これはおそらく問題の原因でしょうか。tomcat のログには -

SEVERE: The web application [/openreports] created a ThreadLocal with key of type [com.opensymphony.xwork2.ActionContext.ActionContextThreadLocal] (value [com.opensymphony.xwork2.ActionContext$ActionContextThreadLocal@7c45901a]) and a value of type [com.opensymphony.xwork2.ActionContext] (value [com.opensymphony.xwork2.ActionContext@3af7dab3]) but failed to remove it when the web application was stopped. This is very likely to create a memory leak.
SEVERE: The web application [/openreports] created a ThreadLocal with key of type [com.opensymphony.xwork2.inject.ContainerImpl$10] (value [com.opensymphony.xwork2.inject.ContainerImpl$10@258c27bd]) and a value of type [com.opensymphony.xwork2.inject.InternalContext[]] (value [[Lcom.opensymphony.xwork2.inject.InternalContext;@1484fc8d]) but failed to remove it when the web application was stopped. This is very likely to create a memory leak.

EDIT:OOMエラーのスタックトレースを追加

java.lang.OutOfMemoryError: Java heap space
        at java.util.Arrays.copyOfRange(Arrays.java:3209)
        at java.lang.String.<init>(String.java:215)
        at java.lang.StringBuffer.toString(StringBuffer.java:585)
        at java.io.StringWriter.toString(StringWriter.java:193)
        at org.displaytag.tags.TableTag.writeExport(TableTag.java:1503)
        at org.displaytag.tags.TableTag.doExport(TableTag.java:1454)
        at org.displaytag.tags.TableTag.doEndTag(TableTag.java:1309)
        at org.efs.openreports.engine.QueryReportEngine.generateReport(QueryReportEngine.java:198)
        at org.efs.openreports.util.ScheduledReportJob.execute(ScheduledReportJob.java:173)
        at org.quartz.core.JobRunShell.run(JobRunShell.java:202)
        at org.quartz.simpl.SimpleThreadPool$WorkerThread.run(SimpleThreadPool.java:529)
10:01:04,193 ERROR ErrorLogger - Job (90.70|1338960412084 threw an exception.
org.quartz.SchedulerException: Job threw an unhandled exception. [See nested exception: java.lang.OutOfMemoryError: Java heap space]
        at org.quartz.core.JobRunShell.run(JobRunShell.java:213)
        at org.quartz.simpl.SimpleThreadPool$WorkerThread.run(SimpleThreadPool.java:529)
Caused by: java.lang.OutOfMemoryError: Java heap space
        at java.util.Arrays.copyOfRange(Arrays.java:3209)
        at java.lang.String.<init>(String.java:215)
        at java.lang.StringBuffer.toString(StringBuffer.java:585)
        at java.io.StringWriter.toString(StringWriter.java:193)
        at org.displaytag.tags.TableTag.writeExport(TableTag.java:1503)
        at org.displaytag.tags.TableTag.doExport(TableTag.java:1454)
        at org.displaytag.tags.TableTag.doEndTag(TableTag.java:1309)
        at org.efs.openreports.engine.QueryReportEngine.generateReport(QueryReportEngine.java:198)
        at org.efs.openreports.util.ScheduledReportJob.execute(ScheduledReportJob.java:173)
        at org.quartz.core.JobRunShell.run(JobRunShell.java:202)
4

1 に答える 1

0

ASP.NET WebForms (MVC ではない) アプリケーションを実行していますか? 私たちのアプリケーションでも同様の問題がありましたが、これらは私たちが遭遇したポイントです. 最初に、私たちの Web ファームは多数のアプリケーション プールで構成されていることをお伝えしておきます。もちろん、クライアントごとに 1 つずつです。各アプリ プールには、クライアントがメモリを制御不能に陥らせず、他のワーカー プロセスに影響を与えないようにするために、特定のメモリ制限が与えられました。

1) オブジェクトがルート化されていない場合でも、それらが 85K を超える場合は、.NET の GC が圧縮しないラージ オブジェクト ヒープに配置されます。つまり、100K のオブジェクトがある場合、LOH に配置されます。オブジェクトがクリーンアップされると、100K が返され、GC はその穴に何か他のものを入れることを決定する可能性があります。圧縮されていないため、スペースが完全に埋まっているとは限りません。これにより、完全に埋められていないスペースに穴が残り、メモリの断片化が発生します。これを解決する唯一の方法は、ダンプ ファイルを調べて、どのオブジェクトが最大のスペースを占めているかを確認し、削減できるクラス/コレクションを特定することです。オブジェクト配列と文字列は通常、キャッシュ マネージャーなどではかなり大きいため、多くのオブジェクト配列と文字列が表示される可能性があります。

2) インスタンスを破棄していますか? ファイナライザー スレッドがクリーンアップ インスタンスに到達するまで待機することは、既定のケースではありません。これは、ひどい GC パフォーマンスにつながる可能性があるためです。継承のどこかに IDisposable インターフェイスを実装するすべてのクラスを破棄していることを確認してください。Dispose を早期に呼び出すということは、リソースが決定論的な方法で解放されることを意味しますが、ファイナライザーに依存するということは、クリーンアップがかなり後で (あったとしても) 行われる可能性があることを意味します。

3) OutOfMemoryExceptions が発生する場合は、次の 2 つの理由が考えられます。マネージド メモリが不足している (リサイクルされるため、制限が設定されたワーカー プロセスの場合はまれです) または仮想メモリが不足しています。 32 ビット IIS アプリケーションで実行している場合、仮想メモリが 2GB に制限されるため、さらに悪いことになります。また、GC が 64MB のヒープ チャンク (ワークステーション モードでは 32GB) を割り当てていて、2GB の制限に近づき、それ以上のスペースを割り当てることができなくなると、例外がスローされた実稼働環境でもこの問題が発生しました (参照: 「ワークステーション」のガベージ コレクションか「サーバー」のガベージ コレクションか? )。このような場合は、

ダンプ ファイルまたは少なくともその関連部分を投稿できれば、問題がどこにあるかを簡単に確認できます。しかし、あなたの簡単な説明から、これらは私が見るアイテムです.

于 2012-12-10T09:37:05.830 に答える