64 ビット .NET Framework で実行されているマネージド アプリケーションでのメモリ不足の例外
この記事は、64 ビットの Microsoft .NET Framework 4.6.1 を対象とするマネージド アプリケーションがある場合のメモリ不足の例外を解決するのに役立ちます。
元の製品バージョン: .NET Framework 4.6.1
元の KB 番号: 3152158
現象
64 ビットの .NET Framework 4.6.1 を対象とするマネージド アプリケーションがあります。 このアプリケーションは、次の特定のメッセージを含むメモリ不足例外を共通言語ランタイム (CLR) からスローします。
OutOfMemoryException: "プログラムの実行を続行するには、指定されたアドレス空間範囲内のメモリが不足しています。"
原因
このメモリ不足例外は、コード マネージャー サブシステムがジャンプ スタブの特定のアドレス空間範囲内にメモリを割り当てることができない場合に、CLR によって伝達されます。 (これらのジャンプ スタブは、アドレス空間で 2 GB 以上離れているダイナミック リンク ライブラリ (DLL) 間で呼び出すメソッドに対応します)。 64 ビット メソッド呼び出しのジャンプ スタブを格納するには、呼び出し元メソッドの 2 GB の半径内にスペースが必要です。 アプリケーションがこの特定のエラーから回復する安全な方法はありません。 そのため、このエラーを満たした後のアプリケーションの状態は不明であり、破損したと見なす必要があります。 回復する唯一の方法は、アプリケーションを再起動することです。
回避策
この問題を回避するには、次のいずれかの設定方法を使用します。
次のレジストリ キーを追加して、コンピューター全体の設定を実装します。
- 場所:
HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\.NETFramework
- 型: DWORD
- 名前: NGenReserveForjumpStubs
- 値: 00000005
- 場所:
次のセクションをアプリケーション構成ファイルに追加して、アプリケーション レベルの設定を実装します。
<configuration> <runtime> <NGenReserveForJumpStubs value="5" /> </runtime> </configuration>
Note
NGenReserveForJumpStubs
では、読み込まれた各 NGen イメージの近くのジャンプ スタブのアドレス空間の割合が CLR によって予約されます。 このOutOfMemoryException
が発生している場合は、5 以上の値を使用することをお勧めします。
開発者向けの情報
.NET Framework は、パフォーマンス上の理由から、メソッド呼び出しを 32 ビットの相対ジャンプとしてエンコードします。 64 ビット システムでは、呼び出し元と呼び出し先を 2 GB より大きく離すことができます (アドレス空間内)。 符号付き 32 ビット オフセットのアドレス範囲を超えるため、.NET は呼び出し元から 2 GB 以内にジャンプ スタブを作成します。 このジャンプ スタブを使用すると、64 ビット アドレス空間内の任意の場所に移動できます。
JIT と NGen の軽減策の動作が若干異なります。 どちらも事前に追加のアドレス空間を予約しますが、この予約が行われるポイントは 2 つの間で異なります。
NGenReserveForJumpStubs
は、仮想 NGen イメージ サイズ (percentReserveForJumpStubs) の割合です。一般的なジャンプ スタブは 12 バイトです。 詳細については、 JUMP_ALLOCATE_SIZEを参照してください。
メモリは、NGen イメージが読み込まれたアドレスの近くに割り当てられ、予約されます (正確なアルゴリズムは EEJitManager::EnsureJumpStubReserve。 メモリは、ジャンプ スタブを割り当てる必要があるとき、および使用可能な他の適切なアドレス空間がない場合にコミットされます。
前述の軽減策では、NGen イメージのコンテンツは変更されません。 NGen イメージのディスク フットプリントは、軽減策の有無にかかわらず同じです。
現在、アプリケーションが制限に近づいていることを検出する適切な方法はありません。
OutOfMemoryException
を監視して、予約済み領域で十分かどうかを判断できます。この特定のエラーは、呼び出し元の 2 GB アドレス範囲内のメモリの可用性に関連しているため、未使用のメモリが多い場合でも、
OutOfMemoryException
を受け取ることがあります。CodeHeapReserveForJumpStubs
の既定値は、上記の問題に関連していない可能性があるため、変更しないでください。 実際のアプリケーションで回避策としてこの設定を調整する必要があるケースは見ていません。NGenReserveForJumpStubs
を高い値に設定すると、パフォーマンスが低下し、他の微妙な問題が公開されるリスクが生じる可能性があります。
IT ユーザー向けの情報
- この問題は、他のバージョンの .NET Framework でも発生する可能性があります。 ただし、この回避策は現在、.NET Framework 4.6.1 にのみ適用されます。
- 特定の実行パターンを持つ大規模なワークロードにのみ影響するまれな問題です。 すべてのワークロードの 99% を超える場合、この問題は発生しません。
- アプリケーションが
OutOfMemoryException
をスローした後、回復する唯一の推奨される方法は、アプリケーションを再起動することです。