Java Platform, Enterprise Edition アプリケーションでのメモリー・リーク

メモリー・リークのタイプはさまざまで、スレッドと ThreadLocal のリーク、ClassLoader のリーク、システム・リソースのリーク、接続のリークなどがあります。メモリー・リークを検出するためのアプローチには、通常、Java™ ヒープまたはネイティブ・ヒープの使用量の緩やかな増加を監視するための Java Virtual Machine Tool Interface (JVMTI) や、パフォーマンス・モニター・インフラストラクチャー (PMI) カウンターの検査が含まれます。

注: WebSphere® Application Server バージョン 8.5 は、実行時のアプリケーション・コードの疑わしいパターンの監視による、トップダウンのパターン・ベースのメモリー・リークの検出、防止、およびアクションを提供します。WebSphere Application Server は、アプリケーションの停止や再デプロイ時のメモリー・リークに対する保護の手段をいくつか備えています。 リークの検出、防止、およびアクションが使用可能の場合、WebSphere Application Server は、アプリケーションとモジュールのアクティビティーをモニターし、アプリケーションまたは個別のモジュールが停止したときは、診断アクションを実行してリークを検出および修正します。 この機能によって、アプリケーションの再デプロイメントの頻度が高い場合でもサーバーをリサイクルする必要がなく、アプリケーションのアップタイムを増加できます。

クラス・ローダーのメモリー・リーク

メモリー・リークの多くは、クラス・ローダーのリークであることが明らかです。Java クラスは、その名前と、これをロードしたクラス・ローダーによって一意的に特定されます。 同じ名前のクラスを単一の JVM で複数回、それぞれ異なるクラス・ローダーでロードできます。Web アプリケーションは、それぞれ独自のクラス・ローダーを取得し、WebSphere Application Server は、アプリケーションを分離するためにこの方法を使用しています。

オブジェクトは、インスタンスの派生元のクラスへの参照を保持します。クラスは、ロードを行ったクラス・ローダーへの参照を保持します。 クラス・ローダーは、ロードした各クラスへの参照を保持します。 Web アプリケーションから単一のオブジェクトへの参照を保持すると、Web アプリケーションによってロードされた各クラスが留まります。 これらの参照は、多くの場合、Web アプリケーションが再ロードされた後も保持されます。再ロードごとに、留まるクラスが増加し、メモリー不足エラーが発生します。

クラス・ローダーのメモリー・リークは、通常、アプリケーション・コードまたは JRE がトリガーしたコードによって発生します。

JRE がトリガーするリーク

メモリー・リークは、Java ランタイム環境 (JRE) のコードがコンテキスト・クラス・ローダーを使用して、アプリケーションの singleton をロードしたときに発生します。 これらの singleton は、コンテキスト・クラス・ローダーを使用した JRE によってロードされるスレッドや他のオブジェクトの可能性があります。

Web アプリケーション・コードが singleton の初期化または静的イニシャライザーをトリガーする場合、次の条件が適用されます。
  • コンテキスト・クラス・ローダーは Web アプリケーション・クラス・ローダーになります。
  • 参照が Web アプリケーション・クラス・ローダーに対して作成されます。 この参照は、ガーベッジ・コレクションされません。
  • クラス・ローダー、およびクラス・ローダーによりロードされるすべてのクラスをメモリーに留めます。

アプリケーションがトリガーしたリーク

アプリケーションがトリガーしたリークのカテゴリーは、次のとおりです。
  • カスタム ThreadLocal クラス
  • ThreadLocal 値としての Web アプリケーション・クラスのインスタンス
  • ThreadLocal 値から間接的に保持される Web アプリケーション・クラスのインスタンス
  • ThreadLocal 疑似リーク
  • Web アプリケーションによって作成された ContextClassLoader およびスレッド
  • 共通クラス・ローダーによってロードされたクラスが作成した ContextClassLoader およびスレッド
  • 静的クラス変数
  • JDBC ドライバーの登録: RMI ターゲット
アプリケーションがトリガーしたリンクについて詳しくは、 http://wasdynacache.blogspot.com/2012/01/websphere-classloader-memory-leak.htmlhttp://www.websphereusergroup.org.uk/wug/files/presentations/31/Ian_Partridge_-_WUG_classloader_leaks.pdf、 およびhttp://www.ibm.com/support/docview.wss?uid=swg1PM39870を参照してください。

現在、WebSphere Application Server は、アプリケーションの停止や再デプロイ時のメモリー・リークに対する保護の手段をいくつか備えています。WebSphere Application Server はアプリケーションとモジュールのアクティビティーをモニターし、アプリケーションや個別のモジュールが停止したときに診断アクションを実行します。

WebSphere Application Server のこのメモリー・リーク機能には、検出、防止、およびアクションの 3 つの部分があります。
  1. 検出: メモリー・リークが検出されると警告を出します。 Web アプリケーションが停止、アンデプロイ、または再ロードされたときに、標準的な API 呼び出しと、リフレクションのいくつかのテクニックを組み合わせて利用します。WebSphere Application Server は、メモリー・リークの既知の原因を確認し、アプリケーションのリークが検出されると、次のような警告を出します。
    [11/17/11 12:01:05:911 EST] 00000005 LeakDetection E   CWMML0015E: The web application [WasSwat#WasSwatWeb.war] created a ThreadLocal with key of type [test.memleak.MyThreadLocal] (value [test.memleak.MyThreadLocal@216c691]) and a value of type [test.memleak.MyCounter] (value [test.memleak.MyCounter@21942ff]) but failed to remove it when the web application was stopped. 
  2. 防止はデフォルトでオンになっており、JRE がトリガーするリークにのみ適用されます。アプリケーション・サーバー・クラス・ローダーがコンテキスト・クラス・ローダーの場合、サーバーの起動時に singleton を初期化することによって、JRE がトリガーするリークが防止されます。
  3. アクション: メモリー・リークを修正するため、予防的なアクションを取ります。これらのアクションには、合理的なデフォルトが指定され、状況に応じて構成されます。
    protected void com.ibm.ws.classloader.clearReferences(){
            if(ENABLE_CLEAR_REFERENCES_JDBC)
    				clearReferencesJdbc();
    		if(ENABLE_CLEAR_REFERENCES_THREADS)
            				clearReferencesThreads();
            if(ENABLE_CLEAR_REFERENCES_THREADLOCALS)
    				clearReferencesThreadLocals();
    		if(ENABLE_CLEAR_REFERENCES_RMI_TARGETS)
            				clearReferencesRmiTargets();
            if(ENABLE_CLEAR_REFERENCES_STATICS)
                clearReferencesStaticFinal();
    }
表 1. リーク修正の要約のマトリックス
リークの原因 修正方法 使用可能化および制御のための WebSphere Application Server Java 仮想マシンのプロパティー
Threadlocal 構成可能な期間でスレッド・プールのスレッドを更新します。 プールからスレッドを取り出すと、スレッドと Threadlocal がガーベッジ・コレクションされます。
  • com.ibm.ws.runtime.component.MemoryLeakConfig.clearReferencesThreadLocal
  • com.ibm.ws.runtime.component.MemoryLeakConfig.renewThreadPoolNames
  • com.ibm.ws.runtime.component.MemoryLeakConfig.threadPoolRenewalDelayFactor
  • com.ibm.ws.util.ThreadPool.DEFAULT_THREAD_RENEWAL_DELAY
HttpClient のキープアライブ・スレッド スレッドを親クラス・ローダーに切り替えます。
  • com.ibm.ws.runtime.component.MemoryLeakConfig.clearReferencesHttpClientKeepAliveThread
Timer スレッド リフレクションを使用して、スケジュール設定されている可能性がある新しいタスクを停止します。
  • com.ibm.ws.runtime.component.MemoryLeakConfig.clearReferencesStopTimerThreads
JVM によって制御されないスレッド スレッドが実行プログラムを使用して開始されている場合、実行プログラムをシャットダウンするか、スレッドを中断します。
  • com.ibm.ws.runtime.component.MemoryLeakConfig.clearReferencesInterruptThreads
JDBC ドライバー Web アプリケーションによって登録され、Web アプリケーションが忘れている JDBC ドライバーを登録抹消します。
  • com.ibm.ws.runtime.component.MemoryLeakConfig.preventJreMemoryLeak
ResourceBundle このクラス・ローダー、またはこのローダーが親クラス・ローダーである任意のクラス・ローダーによってロードされたバンドルの ResourceBundle キャッシュをクリアします。
  • com.ibm.ws.runtime.component.MemoryLeakConfig.preventJreMemoryLeak
RMI ターゲット リフレクションを使用して、sun.rmi.transport.ObjectTable.implTable および sun.rmi.transport.ObjectTable.objTable の値をクリアします。
  • com.ibm.ws.runtime.component.MemoryLeakConfig.preventJreMemoryLeak
静的クラス変数 WebSphere Application Server は、アプリケーション・クラス・ローダーまたはモジュール・クラス・ローダーによってロードされたクラスのすべての静的クラス変数の値を無効にします。
  • com.ibm.ws.runtime.component.MemoryLeakConfig.clearReferencesStatic com.ibm.ws.runtime.component.MemoryLeakConfig.filterPrefixes

トピックのタイプを示すアイコン 概念トピック



タイム・スタンプ・アイコン 最終更新: last_date
http://www14.software.ibm.com/webapp/wsbroker/redirect?version=cord&product=was-nd-mp&topic=ctrb_memleakdetection
ファイル名:ctrb_memleakdetection.html