Dela via


Ett undantag utan minne i ett hanterat program som körs på 64-bitars .NET Framework

Den här artikeln hjälper dig att lösa undantaget för minnesbrist när du har ett hanterat program som är avsett för 64-bitars Microsoft .NET Framework 4.6.1.

Ursprunglig produktversion: .NET Framework 4.6.1
Ursprungligt KB-nummer: 3152158

Symptom

Du har ett hanterat program som riktar sig mot 64-bitars .NET Framework 4.6.1. Det här programmet genererar ett out-of-memory-undantag från Common Language Runtime (CLR) med följande specifika meddelande:

OutOfMemoryException: "Otillräckligt minne inom det angivna adressutrymmet för att fortsätta körningen av programmet."

Orsak

Det här out-of-memory-undantaget sprids av CLR när undersystemet code manager inte kan allokera minne inom ett specifikt adressutrymmesintervall för jump stubs. (Dessa hoppstubbar motsvarar metoden som anropar bland DLL:er (Dynamic-Link Libraries) som ligger 2 GB eller mer ifrån varandra i adressutrymmet.) Det måste finnas utrymme inom en radie på 2 GB från anropande metod för att lagra jump stub för ett 64-bitars metodanrop. Det finns inget säkert sätt för ett program att återställa från det här specifika felet. Så tillståndet för programmet när det uppfyller det här felet är okänt och bör betraktas som skadat. Det enda sättet att återställa är att starta om programmet.

Lösning

Du kan lösa det här problemet genom att använda någon av följande inställningsmetoder:

  • Implementera en datoromfattande inställning genom att lägga till följande registernyckel:

    • Plats: HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\.NETFramework
    • Typ: DWORD
    • Namn: NGenReserveForjumpStubs
    • Värde: 00000005
  • Implementera en inställning på programnivå genom att lägga till följande avsnitt i programkonfigurationsfilen:

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

    Obs!

    NGenReserveForJumpStubs gör att CLR reserverar en procentandel av adressutrymmet för hoppstubbar nära varje inläst NGen-avbildning. Vi rekommenderar att du använder värdet 5 eller senare om du upplever det här OutOfMemoryException.

Information för utvecklare

  • .NET Framework kodar metodanrop som relativa 32-bitarshopp av prestandaskäl. I ett 64-bitarssystem kan uppringaren och anroparen vara längre ifrån varandra än 2 GB (i adressutrymme). Eftersom den överskrider adressintervallet för en signerad 32-bitarsförskjutning skapar .NET en hoppstub inom 2 GB av anroparen. Den här hoppstuben kan sedan göra det långa hoppet till var som helst i 64-bitars adressutrymmet.

  • JIT- och NGen-minskningarna fungerar något annorlunda. Båda reserverar extra adressutrymme i förväg, men den punkt där reservationen görs skiljer sig åt mellan de två.

  • NGenReserveForJumpStubs är en procentandel av storleken på den virtuella NGen-avbildningen (percentReserveForJumpStubs).

  • En typisk hoppstub är 12 byte. Mer information finns i JUMP_ALLOCATE_SIZE.

  • Minnet allokeras och reserveras nära adressen där NGen-avbildningen lästes in (den exakta algoritmen är EEJitManager::EnsureJumpStubReserve. Minnet checkas in när det finns ett behov av att allokera en jump stub och när det inte finns något annat lämpligt adressutrymme tillgängligt.

  • Den tidigare nämnda åtgärden ändrar inte innehållet i NGen-bilder. NGen-avbildningarna har samma diskavtryck både med och utan åtgärd.

  • Det finns för närvarande inget bra sätt att identifiera när programmet närmar sig gränsen. Du kan övervaka för OutOfMemoryException att avgöra om det reserverade utrymmet är tillräckligt.

  • Du kan få OutOfMemoryException även om det finns mycket oanvänt minne eftersom det här specifika felet är relaterat till tillgängligheten för minne inom en radie på 2 GB för anroparen.

  • Ändra inte standardvärdet CodeHeapReserveForJumpStubsför eftersom det kanske inte är relaterat till problemet som beskrivs ovan. Vi har inte sett ett fall där det faktiska programmet skulle behöva justera den här inställningen som en lösning.

  • Om du anger NGenReserveForJumpStubs ett högre värde kan det leda till lägre prestanda och risk för att andra subtila problem exponeras.

Information för IT-användare

  • Det här problemet kan också inträffa i andra versioner av .NET Framework. Lösningen gäller dock för närvarande endast för .NET Framework 4.6.1.
  • Det är ett sällsynt problem som bara påverkar stora arbetsbelastningar som har ett visst körningsmönster. Mer än 99 procent av alla arbetsbelastningar kommer någonsin att uppleva det här problemet.
  • När programmet har skapats OutOfMemoryExceptionär det enda rekommenderade sättet att återställa att starta om programmet.