共用方式為


在 64 位 .NET Framework 上執行的受控應用程式中發生記憶體不足例外狀況

當您有以 64 位Microsoft .NET Framework 4.6.1 為目標的受控應用程式時,本文可協助您解決記憶體不足例外狀況。

原始產品版本: .NET Framework 4.6.1
原始 KB 編號: 3152158

徵兆

您有一個以 64 位 .NET Framework 4.6.1 為目標的受控應用程式。 此應用程式會從 Common Language Runtime (CLR) 擲回記憶體不足例外狀況,並顯示下列特定訊息:

OutOfMemoryException:「指定地址空間範圍內的記憶體不足,無法繼續執行程式。

原因

當程式代碼管理員子系統無法在跳躍存根的特定位址空間範圍內配置記憶體時,CLR 會傳播這個記憶體不足的例外狀況。 (這些跳躍存根對應於在位址空間中位於 2 GB 或以上的動態連結庫 (DLL) 之間呼叫的方法。 呼叫方法的 2 GB 半徑內必須有空間,才能儲存 64 位方法呼叫的跳躍存根。 應用程式無法從這個特定錯誤復原。 因此,應用程式在遇到此錯誤之後的狀態是未知的,因此應該將其視為損毀。 復原的唯一方法是重新啟動應用程式。

因應措施

若要解決此問題,請使用下列其中一個設定方法:

  • 藉由新增下列登錄機碼來實作全機器設定:

    • 位置:HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\.NETFramework
    • 類型: DWORD
    • 名稱:NGenReserveForjumpStubs
    • 值:00000005
  • 將下列區段新增至您的應用程式組態檔,以實作應用層級設定:

    <configuration>
        <runtime>
            <NGenReserveForJumpStubs value="5" />
        </runtime>
    </configuration>
    

    注意

    NGenReserveForJumpStubs 會讓 CLR 保留每個載入 NGen 映射附近跳躍存根的位址空間百分比。 如果您遇到這個 OutOfMemoryException,建議您使用 5 或更新的值。

開發人員的資訊

  • 基於效能考慮,.NET Framework 會將方法呼叫編碼為相對的 32 位跳躍。 在 64 位系統上,呼叫者和被呼叫者可以比 2 GB(在地址空間中)更遠。 因為它超過帶正負號 32 位位位移的位址範圍,所以 .NET 會在呼叫端的 2 GB 內建立跳躍存根。 然後,這個跳躍存根可以跳到 64 位位址空間中的任何位置。

  • JIT 和 NGen 風險降低的運作方式稍有不同。 兩者都會預先保留額外的位址空間,但兩者之間的保留點不同。

  • NGenReserveForJumpStubs 是虛擬 NGen 映射大小的百分比(percentReserveForJumpStubs)。

  • 典型的跳躍存根是 12 個字節。 如需詳細資訊,請參閱 JUMP_ALLOCATE_SIZE

  • 記憶體會配置並保留到載入 NGen 映像的位址附近(確切演算法為 EEJitManager::EnsureJumpStubReserve。 當需要配置跳躍存根,且沒有其他適當的位址空間可用時,就會認可記憶體。

  • 先前提到的風險降低不會修改 NGen 映像的內容。 NGen 映像具有與 無風險降低的相同磁碟使用量。

  • 目前沒有好方法可偵測應用程式何時接近限制。 您可以監視 , OutOfMemoryException 以判斷保留空間是否足夠。

  • 即使記憶體太多未使用,您還是會收到 OutOfMemoryException ,因為這個特定錯誤與呼叫端 2 GB 位址範圍半徑記憶體的可用性有關。

  • 請勿變更 的預設值 CodeHeapReserveForJumpStubs,因為它可能與上述問題無關。 我們沒有看到實際應用程式必須調整此設定作為因應措施的情況。

  • 將 設定 NGenReserveForJumpStubs 為較高的值可能會導致效能降低,以及暴露其他微妙問題的風險。

IT 用戶的資訊

  • 此問題也可能發生在其他 .NET Framework 版本上。 不過,因應措施目前僅適用於 .NET Framework 4.6.1。
  • 只有影響具有特定執行模式的大型工作負載,這是罕見的問題。 超過 99% 的所有工作負載永遠不會遇到此問題。
  • 在應用程式擲回 之後,復原的唯一 OutOfMemoryException建議方式是重新啟動應用程式。