Поделиться через


Исключение вне памяти в управляемом приложении, работающем на 64-разрядном платформа .NET Framework

Эта статья поможет устранить исключение вне памяти, если у вас есть управляемое приложение, предназначенное для 64-разрядной версии Microsoft платформа .NET Framework 4.6.1.

Исходная версия продукта: платформа .NET Framework 4.6.1
Исходный номер базы знаний: 3152158

Симптомы

У вас есть управляемое приложение, которое предназначено для 64-разрядной платформа .NET Framework 4.6.1. Это приложение выдает исключение из среды CLR (CLR) вне памяти со следующим сообщением:

OutOfMemoryException: "Недостаточно памяти в заданном диапазоне адресного пространства для продолжения выполнения программы".

Причина

Это исключение вне памяти распространяется средой CLR, когда подсистема диспетчера кода не может выделить память в определенном диапазоне адресного пространства для заглушки переходов. (Эти заглушки переходов соответствуют методу, который вызывает библиотеки динамического канала (DLL), расположенные в адресном пространстве 2 ГБ или больше друг от друга.) Пространство должно находиться в радиусе 2 ГБ вызывающего метода, чтобы сохранить заглушку прыжка для вызова 64-разрядного метода. Нет безопасного способа восстановления приложения после этой конкретной ошибки. Таким образом, состояние приложения после того, как оно соответствует этой ошибке неизвестно, и его следует считать поврежденным. Единственным способом восстановления является перезапуск приложения.

Обходное решение

Чтобы обойти эту проблему, используйте один из следующих методов настройки:

  • Реализуйте параметр на уровне компьютера, добавив следующий раздел реестра:

    • Расположение: HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\.NETFramework
    • Тип: DWORD
    • Имя: NGenReserveForjumpStubs
    • Значение: 00000005
  • Реализуйте параметр уровня приложения, добавив следующий раздел в файл конфигурации приложения:

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

    Примечание.

    NGenReserveForJumpStubs Среда CLR резервирует процент адресного пространства для заглушки прыжков вблизи каждого загруженного образа NGen. Рекомендуется использовать значение 5 или больше, если вы испытываете эту OutOfMemoryExceptionошибку.

Сведения для разработчиков

  • Метод платформа .NET Framework кодирует вызовы метода в виде относительных 32-разрядных переходов по соображениям производительности. В 64-разрядной системе вызывающий объект и вызывающий объект могут быть более 2 ГБ (в адресном пространстве). Так как он превышает диапазон адресов со знаком 32-разрядного смещения, .NET создаст заглушку прыжка в пределах 2 ГБ вызывающего объекта. Эта заглушка прыжка может сделать длинный переход в любое место в 64-разрядном адресном пространстве.

  • Устранение рисков JIT и NGen немного отличается. Оба из них резервирует дополнительное адресное пространство вперед, но точка, в которой это резервирование отличается от двух.

  • NGenReserveForJumpStubs — это процент размера виртуального образа NGen (percentReserveForJumpStubs).

  • Типичная заглушка прыжка составляет 12 байт. Дополнительные сведения см. в JUMP_ALLOCATE_SIZE.

  • Память выделена и зарезервирована близко к адресу, в котором загружен образ NGen (точный алгоритм — EEJitManager::EnsureJumpStubReserve. Память фиксируется, если необходимо выделить заглушку прыжка, и когда нет другого подходящего адресного пространства.

  • Ранее упомянутые меры по устранению рисков не изменяют содержимое образов NGen. Образы NGen имеют одинаковый объем дискового пространства и без устранения рисков.

  • В настоящее время нет хорошего способа определить, когда приложение приближается к ограничению. Вы можете отслеживать, OutOfMemoryException чтобы определить, достаточно ли зарезервированное пространство.

  • Вы можете получить OutOfMemoryException даже в том случае, если неиспользуемая память, так как эта конкретная ошибка связана с доступностью памяти в радиусе диапазона адресов 2 ГБ вызывающего объекта.

  • Не изменяйте значение CodeHeapReserveForJumpStubsпо умолчанию, так как оно не может быть связано с проблемой, описанной выше. Мы не видели ситуации, когда фактическое приложение потребуется изменить этот параметр в качестве обходного решения.

  • Установка NGenReserveForJumpStubs более высокого значения может привести к снижению производительности и риску предоставления других тонких проблем.

Сведения для ИТ-пользователей

  • Эта проблема также может возникать в других версиях платформа .NET Framework. Однако решение в настоящее время применимо только к платформа .NET Framework 4.6.1.
  • Это редкая проблема, которая влияет только на большие рабочие нагрузки, имеющие определенный шаблон выполнения. Более 99 процентов всех рабочих нагрузок никогда не будут сталкиваться с этой проблемой.
  • После того как приложение выдает исключение, рекомендуемый OutOfMemoryExceptionспособ восстановления — перезапустить приложение.