JetBrains Rider 2026.1 Help

GC ルートの分析

オブジェクトの保持パスは常に GC ルートから始まります。 ガーベジコレクタの観点からすると、ルートは収集されてはいけないし、収集されることもないオブジェクトへの参照です。 これにより、ルートは保持グラフを作成する際の唯一の開始点となります。 「誰がオブジェクトを保持しているのか?」の分析時には、ルートの種類の理解が重要になる場合があります。 保持パスを調べても、なぜオブジェクトがまだメモリに残っているのかわからない場合もあります。 この場合は、GC ルートを確認するのが適切です。 例えば、 RefCounted 処理するは、アンマネージ COM ライブラリがそのオブジェクトを保持していることを示します。

.NET には 4 つのルートタイプがあります。

  • スタック参照: ローカルオブジェクトへの参照。 このようなルートはメソッドの実行中に存続します。

  • 静的参照: 静的オブジェクトへの参照。 これらのルートは、アプリドメインの存続期間全体にわたって存続します。

  • ハンドル: 通常、これらは管理対象コードと管理対象外コード間の通信に使用される参照です。 そのようなルートは、少なくともアンマネージコードが「管理された」オブジェクトを必要とするまで存続しなければなりません。

  • ファイナライザの参照: ファイナライズされるのを待っているオブジェクトへの参照。 これらのルートはファイナライザが実行されるまで生き続けます。

保持パスのルートを分析するには、オブジェクト保持パスを表示する ルートへの最短パス ビューを使用します。 dotMemory によって区別されるすべてのルートタイプは、上記のリストに記載されているカテゴリのいずれかに分類されることに注意してください。

通常のローカル変数

メソッド内で宣言されたローカル変数(スタック上の変数)です。 この変数への参照は、メソッドの存続期間中はルートになります。 例えば:

static void Main() { ... var collection = new Collection <int>(); ... }
正規ローカル変数ルート

リリースビルドではルートの存続期間が短くなる場合があることに注意してください。JIT により、不要になった変数はすぐに破棄されます。

静的リファレンス

CLR は、静的オブジェクト (クラスメンバー、変数、イベント) に遭遇すると、このオブジェクトのグローバルインスタンスを作成します。 オブジェクトはアプリの有効期間中ずっとアクセスできるため、静的オブジェクトが収集されることはほとんどありません。 静的オブジェクトへの参照は、主要なルート型の 1 つです。

class SomeClass { public static Collection<string> StCollection; }

コレクションが初期化された後、CLR はコレクションの静的インスタンスを作成します。 インスタンスへの参照は、アプリケーションドメインの有効期間中に存在します。

静的参照ルート

静的オブジェクトがフィールドを介して参照されると、dotMemory はフィールドの名前を表示します。

F 到達可能キュー / ファイナライズキュー

CLR は、アンマネージリソースを解放するための便利なメカニズム、ファイナライズパターンを提供します。 System.Object 型は、オブジェクトのメモリが再利用される前にガベージコレクターによって呼び出される仮想メソッド Finalize (ファイナライザーとも呼ばれます) を宣言します。 通常、このメソッドをオーバーライドしてアンマネージリソースを解放します。 ファイナライザーを持つオブジェクトはすべて、ファイナライズキューに入れられます (dotMemory では、これらのオブジェクトのルートは ファイナライズキュー​​ノ隊列 Finalization Queue Finalization Queue Finalization Queue です)。 ガベージコレクションが行われると、GC はファイナライズキューでそのようなオブジェクトを見つけますが、ファイナライザーを直接実行しません。 代わりに、GC はオブジェクトを F 到達可能キュー (dotMemory では F 到達可能キュー​​ノ隊列 F-Reachable Queue F-Reachable Queue F-Reachable Queue ルート) に入れ、ファイナライザーを別のファイナライズスレッドで実行します (ファイナライザーは任意の量のコードを実行できるため、これはパフォーマンスのために行われます)。 次の GC では、F 到達可能キューのオブジェクトがガベージコレクションされます。

メモリプロファイリングの性質上、dotMemory はスナップショットを取得する前に必ずフル GC を実行します。 そのため、dotMemory で取得したスナップショットには ファイナライズキュー​​ノ隊列 Finalization Queue Finalization Queue Finalization Queue ルートのオブジェクトは見つかりません。 このルートタイプは、生のメモリダンプでのみ可能です。

F キュールート

ピンニングハンドル

マネージドコードとアンマネージコードの相互作用は、ガーベジコレクタにとって追加の問題となります。 例えば、マネージド ヒープのオブジェクトを外部 API ライブラリなどに渡す必要があります。 小さいオブジェクト ヒープがコレクション中に圧縮されると、オブジェクトが移動される場合があります。 アンマネージコードが厳密なオブジェクトの位置に依存している場合、これは問題となります。 解決策の一つは、ヒープ内でオブジェクトを固定することです。 この場合、GC はそのオブジェクトへのピン留め処理するを取得し、そのオブジェクトは移動できなくなります(ピン留めオブジェクト)。 したがって、 ピンニングハンドル ルートが表示されている場合、オブジェクトはアンマネージコードによって保持されている可能性があります。 例えば、 App オブジェクトは常に固定参照を持っています。

固定ハンドルの根元

さらに、スナップショットで ピンニングハンドル が表示される場合があります。 場合によっては、 静的参照を正しく特定できないことがあります。その場合、 静的リファレンス ルートの代わりに、 ピンニングハンドル ルートによって保持されているオブジェクトの配列 Object[] が表示されることがあります。 これが、静的参照の仕組みを正しく表しています。

静的参照ルートの代わりにハンドルルートを固定する
固定されたオブジェクト

内部ローカル変数

管理対象オブジェクトはガベージコレクション中に移動される可能性があるため(ピン留め処理するを参照)、ネイティブポインターを使ってヒープ上の位置をトラックすることはできません。 このような場合は、 内部ポインターを使用できます。 内部ポインターは、参照型の内部へのポインターを宣言しますが、オブジェクト自体へのポインターを宣言しません。 オブジェクトを保持する 内部ローカル変数 ルートが表示されている場合は、このオブジェクトの内部を指す内部ポインターが存在する可能性があります。 例については、 マイクロソフトラーンを参照してください。

内部ローカル変数

RefCounted ハンドル

ルートは、オブジェクトの参照カウントが特定の値である場合、ガベージコレクションを防止します。 COM 相互運用機能を使用してオブジェクトが COM ライブラリに渡される場合、CLR はこのオブジェクトへの RefCounted ハンドルを作成します。 COM はガベージコレクションを実行できないため、このルートが必要になります。 代わりに、参照カウントを使用します。 オブジェクトが不要になった場合、COM はカウントを 0 に設定します。 これは、 RefCounted ハンドルがルートではなくなり、オブジェクトを収集できることを意味します。

RefCounted ハンドル と表示された場合、おそらく、オブジェクトはアンマネージコードの引数として渡されます。

RefCounted ハンドルルート

弱いハンドル

他のルートとは異なり、弱いハンドルは参照されたオブジェクトのガベージコレクションを妨げません。 オブジェクトはいつでも収集できますが、アプリケーションからアクセスできます。 このようなオブジェクトへのアクセスは、 WeakReference タイプの中間オブジェクトを介して実行されます。 このようなアプローチは、キャッシュなどの一時的なデータ構造を操作する場合に効率的です。 弱い参照は完全なガベージコレクションを生き残れないため、弱い参照ハンドルは他のハンドルと組み合わせてのみ使用できます。 例: 弱い、RefCounted ハンドル

弱いハンドル根

レギュラーハンドル

ハンドルタイプが未定義の場合、dotMemory はそれを レギュラーハンドル としてマークします。 通常、これらはアプリの存続期間中に必要なシステムオブジェクトへの参照です。 例: OutOfMemoryException オブジェクト。 コレクションを防ぐために、環境は通常のハンドルを通じてオブジェクトを参照します。

通常のハンドルルート
2026 年 6 月 12 日