Out-of-memory exception in a managed application that's running on the 64-bit .NET Framework
You have a managed application that targets the 64-bit Microsoft .NET Framework 4.6.1. This application throws an out-of-memory exception from the CLR with the following specific message:
OutOfMemoryException: "Insufficient memory within specified address space range to continue the execution of the program."
This out-of-memory exception is propagated by the CLR when the code manager subsystem cannot allocate memory within a specific address space range for jump stubs. (These jump stubs correspond to the method that calls among DLLs that are located 2 GB or more apart in the address space.) There must be space within a 2-GB radius of the calling method to store the jump stub for a 64-bit method call. There is no safe way for an application to recover from this specific error. Therefore, the state of the application after it encounters this error is unknown and it should be considered corrupted. The only way to recover is to restart the application.
To work around this issue, use one of the following setting methods:
- Implement a machine-wide setting by adding the following registry key and value: HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\.NETFramework
- Implement an application-level setting by adding (or merging) the following section to your application config file:
<configuration> <runtime> <NGenReserveForJumpStubs value="5" /> </runtime></configuration>
- The .NET Framework encodes method calls as relative 32-bit jumps for performance reasons. On a 64-bit system, caller and callee can be further apart than 2 GB (in address space). Because this exceeds the address range of a signed 32-bit offset, .NET will create a jump stub within 2 GB of the caller. This jump stub can then make the “long” jump to anywhere in the 64-bit address space.
- The JIT and NGen mitigations work slightly differently. Both of them reserve extra address space up front, but the point where this reservation is made differs between the two.
- NGenReserveForJumpStubs is a percentage of virtual NGen image size (percentReserveForJumpStubs).
- A typical jump stub is 12 bytes. For more information, see JUMP_ALLOCATE_SIZE.
- The memory is allocated and reserved close to the address where the NGen image was loaded (the exact algorithm is EEJitManager::EnsureJumpStubReserve). The memory is committed when there is a need to allocate a jump stub, and when there is no other suitable address space available.
- The previously mentioned mitigation doesn’t modify the content of NGen images. The NGen images have the same disk footprint both with and without mitigation.
- There is currently no good way to detect when the application is getting close to the limit. You must monitor for the OutOfMemoryException to determine whether the reserved space is sufficient.
- You may receive the OutOfMemoryException even if there is a lot of unused memory because this specific error is related to the availability of memory within a 2-GB address range radius of the caller.
- You shouldn’t change the default value of CodeHeapReserveForJumpStubs, because it may not be related to the issue described above. We have not seen case where the actual application would have to adjust this setting as a workaround.
- Setting NGenReserveForJumpStubs to a significantly higher value may lead to reduced performance and the risk of exposing other subtle issues.
For IT users
- This issue may also occur on other versions of the .NET Framework. However, the workaround is currently applicable only to the .NET Framework 4.6.1.
- This is a very rare issue that only affects very large workloads that have a very particular execution pattern. More than 99 percent of all workloads will ever experience this issue.
- After the application throws an OutOfMemory exception, the only recommended way to recover is to restart the application.
Article ID: 3152158 - Last Review: 05/10/2016 16:37:00 - Revision: 3.0
Microsoft .NET Framework 4.6.1
- kbsurveynew kbtshoot kbexpertiseinter KB3152158