最近、サーバー アプリケーション (Windows サービス) の 1 つが OutOfMemory 例外で失敗したことがわかりました。何が起こっているのかを調べようとしましたが、ファイナライズ キュー内のオブジェクトがファイナライズされていないため、ガベージ コレクションが発生しません。Windbg を使用して、どのファイナライザーがこの動作を引き起こす可能性があるかを調べようとしましたが、どのオブジェクトが原因であるかを正確に特定することはできません。
!finalizequeue コマンドを使用すると、次のことがわかります。
0:053> !ファイナライズキュー clr.dll の PDB シンボルがロードされていません クリーンアップする SyncBlocks: 0 リリース予定のフリースレッド インターフェイス: 0 リリースされる MTA インターフェイス: 0 解放される STA インターフェイス: 0 ---------------------------------- ジェネレーション 0 には 28 個のファイナライズ可能なオブジェクトがあります (050eab4c->050eabbc) ジェネレーション 1 には 15 個のファイナライズ可能なオブジェクトがあります (050eab10->050eab4c) 第 2 世代には 658 個のファイナライズ可能なオブジェクトがあります (050ea0c8->050eab10) ファイナライズの準備完了 3027 オブジェクト (050eabbc->050edb08) ...
3027 は信じられないほど高い数値です (数分間実行した後ですが、この数値はまだ増加しており、決して低下していません)。アドレス 050eabbc にあるオブジェクトを見つけようとしましたが、常に異なるタイプなので、それが原因ではないと思います。
ファイナライザー スレッドのネイティブ コール スタックを出力しようとすると、次のようになりました。
0:053> ~2k *** エラー: シンボル ファイルが見つかりませんでした。C:\Windows\SYSTEM32\KERNELBASE.dll のシンボルをエクスポートするようにデフォルト設定 - ChildEBP RetAddr 警告: スタック アンワインド情報は利用できません。次のフレームは間違っている可能性があります。 032ef09c 772f10b4 ntdll!ZwWaitForSingleObject+0xc *** エラー: シンボル ファイルが見つかりませんでした。C:\Windows\SYSTEM32\combase.dll のシンボルをエクスポートするようにデフォルト設定 - 032ef0b0 755ff0b5 カーネルベース!WaitForSingleObject+0x12 032ef0e4 7554b22a コンベース!NdrOleDllGetClassObject+0x1399 032ef108 755ff10c コンベース!PropVariantCopy+0x177b 032ef224 75511724 コンベース!NdrOleDllGetClassObject+0x13f0 032ef27c 7558115d コンベース!DcomChannelSetHResult+0x17c7 032ef2d8 755fd39a コンベース!CoRegisterSurrogateEx+0x3494 *** エラー: シンボル ファイルが見つかりませんでした。C:\Windows\SYSTEM32\RPCRT4.dll のシンボルをエクスポートするようにデフォルト設定 - 032ef2f4 76a9e4a0 コンベース!NdrExtStubInitialize+0x21a9 032ef71c 755fc779 RPCRT4!NdrComplexArrayUnmarshall+0xcac 032ef738 75510d77 コンベース!NdrExtStubInitialize+0x1588 032ef748 755816d5 コンベース!DcomChannelSetHResult+0xe1a 032ef7dc 75587aa5 compase!CoRegisterSurrogateEx+0x3a0c *** エラー: シンボル ファイルが見つかりませんでした。C:\Windows\Microsoft.NET\Framework\v4.0.30319\clr.dll のシンボルをエクスポートするようにデフォルト設定 - 032ef82c 748ab680 コンベース!StringFromIID+0x28d 032ef92c 748ab758 clr!PreBindAssemblyEx+0x259d 032ef964 7487960d clr!PreBindAssemblyEx+0x2675 032ef980 748ab55a clr!GetMetaDataInternalInterfaceFromPublic+0x2162a 032ef9dc 74878915 clr!PreBindAssemblyEx+0x2477 032efa2c 7487887c clr!GetMetaDataInternalInterfaceFromPublic+0x20932 032efa44 7478a5e2 clr!GetMetaDataInternalInterfaceFromPublic+0x20899 032efa8c 74777d71 clr!GetPrivateContextsPerfCounters+0x968
ファイナライザー スレッドは常に ZwWaitForSingleObject でスタックしているため、これはファイナライザー スレッドがスタックしているという別の手がかりです。
私の質問は、どのオブジェクトがファイナライザー キューのスタックを引き起こしているかを調べるにはどうすればよいかということです。面白いことに、私はファイナライザーをまったく使用していません:-(