このページでは、Java メモリリークを検出してトラブルシューティングする方法について説明します。

  • 自動リーク検知を有効化するには、Configure Agent Properties 権限が必要です。
  • オンデマンド キャプチャ セッションを開始するには、Advanced Agent Operation 権限が必要です。「カスタムロールの作成と管理」を参照してください。

JVMのガベージコレクション機能により、コードベースにメモリリークが発生する機会は大幅に減少します。しかし、ガベージコレクションではメモリリークが完全に除去されないため、AppDynamics にはサポートされる JVM の自動リーク検知機能が含まれています。

自動リーク検出

ノードダッシュボードの [Memory] タブで [Automatic Leak Detection] にアクセスできます。[Automatic Leak Detection] は、JVM のオーバーヘッドを増加させるため、デフォルトでは無効になっています。メモリリークの問題が疑われる場合にのみリーク検知モードを有効化してください。リークの原因を特定したら、[Automatic Leak Detection] は無効にします。

自動リーク検知は、On Demand Capture Sessions を使用して、キャプチャ期間内に積極的に使用されるコレクション(JDK Map または Collection インターフェイスを実装するクラス)をキャプチャします。デフォルトのキャプチャ期間は10分です。

AppDynamicsは、以下の基準を満たすすべてのJavaコレクションを追跡します。

  • コレクションが少なくとも 30 分間有効となる。
  • コレクションに少なくとも 1000 個のエレメントがある。 
  • コレクションのディープサイズは少なくとも5 MB。エージェントは、コレクションのすべてのオブジェクトについて再帰的にオブジェクトグラフを横断し、ディープサイズを計算する。

リーク検知基準のデフォルトは、以下のノードプロパティで定義されます。

  • minimum-age-for-evaluation-in-minutes

  • minimum-number-of-elements-in-collection-to-deep-size

  • minimum-size-for-evaluation-in-mb

詳細については、アプリケーションエージェントのノードプロパティを参照してください。 

Javaエージェントはコレクションを追跡し、線形回帰モデルを使ってリークの可能性を識別します。一定期間のコレクションへの頻繁なアクセスを追跡することで、リークの根本原因を特定できます。

コレクションが基準を満たすと、AppDynamics はコレクションのサイズの長期的な成長傾向をモニタリングします。プラスの成長は、コレクションがメモリリークの元である可能性を示しています。

AppDynamicsがリーク元コレクションを特定すると、Javaエージェントは30分ごとに自動的に診断をトリガーします。診断では、コードパスのシャローコンテンツダンプとアクティビティトレース、およびコレクションにアクセスするビジネストランザクションがキャプチャされます。エージェントによってモニタリングされるリーク元コレクションをドリルダウンすることで、コンテンツサマリキャプチャセッションとアクセストラッキングセッションを手動でトリガーできます。

また、カスタムメモリ構造のメモリリークをモニタリングすることもできます。通常、カスタムメモリ構造はキャッシングソリューションとして使用されます。分散環境では、キャッシングがメモリリークの主な原因になりやすい傾向があります。そのため、こうしたメモリ構造のメモリ統計を管理および追跡することが重要です。それには、事前にカスタムメモリ構造を構成する必要があります。詳細については、「Javaのカスタムメモリ構造」を参照してください。

メモリリークのトラブルシューティングのワークフロー

次のワークフローを使用して、メモリリークの問題の可能性があると識別された JVM でメモリリークをトラブルシューティングします。

  1. JVM メモリリークの可能性についてメモリをモニタリングする。
  2. 自動リーク検知を有効化する。
  3. オンデマンド キャプチャ セッションを開始する。
  4. リークの状態を検出およびトラブルシューティングする。

JVMリークの可能性があるメモリのモニタリング

[Node] ダッシュボードを使用してメモリリークを特定します。メモリリークの可能性は、ヒープの増加傾向とOld/Tenured世代のメモリプールからわかります。

急激に増加に傾いている場合、オブジェクトは自動的にリークの可能性があるオブジェクトとしてマークされます。

[Automatic Memory Leak] ダッシュボードには、次のものが表示されます。

  • Collection Size:コレクションのエレメントの数。
  • Potentially Leaking:リークしている可能性のあるコレクションは赤で表示される。リークの可能性があるオブジェクトに対して診断セッションを開始する必要がある。
  • Status:診断セッションがオブジェクトで開始された場合に示される。
  • Collection Size Trend:急激に増加に傾いている場合はメモリリークの可能性がある。

長期のコレクションを特定するには、JVMの開始時間とオブジェクト作成時間を比較します。

キャプチャされたコレクションが表示されない場合は、潜在的なメモリリークを検出するための構成が正しいことを確認してください。

メモリリーク検知の有効化

[Automatic Leak Detection] 機能によって、メモリリーク検出を行うことができます。[Automatic Leak Detection] 機能が有効化され、キャプチャセッションが開始されると、AppDynamics は頻繁に使用されるコレクションをすべて追跡します。そのため、このモードを使用するとオーバーヘッドが大きくなります。

  1. メモリリークの問題が特定された場合にのみ、[Automatic Leak Detection] モードをオンにします。
  2. [Start On Demand Capture Session] をクリックして、頻繁に使用されるコレクションのモニタリングを開始し、リークしているコレクションを検出します。
  3. リークを特定し、解決したら、キャプチャセッションとリーク検知モードをオフにします。
  4. 最適なパフォーマンスを実現するには、1 回につきひとつのコレクションを診断します。

メモリリークのトラブルシューティング

メモリリークの可能性が検出されたら、リークのトラブルシューティングとして次の 3 つのアクションを実行します。

モニタリングするコレクションオブジェクトの選択

自動リーク検知ダッシュボードで、クラス名を右クリックし、[Drill Down] をクリックします。

パフォーマンス上の理由から、一度にひとつのコレクションオブジェクトでトラブルシューティング セッションを開始します。

コンテンツ検査の使用

コンテンツ検査は、トラブルシューティングを開始できるように、コレクションがアプリケーションのどの部分に属するかを特定します。特定のコレクションの要素すべてのヒストグラムをモニタリングできます。

オンデマンドキャプチャセッションを開始して自動リーク検知を有効化し、トラブルシューティングを行うオブジェクトを選択して以下の手順を行います。

  1. [Content Inspection] タブをクリック。
  2. [Start Content Summary Capture Session] をクリックし、コンテンツ検査セッションを開始する。
  3. セッション期間を入力。データ生成に少なくとも1〜2分を割り当てる。
  4. [Refresh] をクリックし、セッションデータを取得する。
  5. スナップショットをクリックし、各セッションの詳細を表示する。

アクセストラッキングの使用

アクセストラッキングを使用して、コレクションオブジェクトにアクセスする実際のコードパスとビジネストランザクションを表示します。

上記の「Workflow to Troubleshoot Memory Leaks」にあるといて、自動リーク検知を有効化し、オンデマンド キャプチャ セッションを開始し、トラブルシューティングを行うオブジェクトを選択して以下の手順を行います。

  1. [Access Tracking] タブを選択。
  2. [Start Access Tracking Session] をクリックし、トラッキングセッションを開始する。
  3. セッション期間を入力。データ生成に少なくとも1-2分を割り当てる。
  4. [Refresh] をクリックし、セッションデータを取得する。
  5. スナップショットをクリックし、各セッションの詳細を表示する。

トラブルシューティング情報ペインには、セッションに関連するJavaスタックトレースが表示されます。デフォルトで、スタックトレースは10行目までの深さで表示されます。一時的にキャプチャされる行数を増やしたい場合は、「アプリケーションエージェントのノードプロパティ参照資料」に記載されている maximum-activity-trace-stack-depth Java エージェントプロパティを使用します。

スタックトレースの深さを増やすと、システムリソースを大きく消費します。必要な情報をキャプチャした後は、そのプロパティを削除するか、デフォルト値 10 に戻してください。