Hur hanterar man "java.lang.OutOfMemoryError: Java heap space" fel?

Jag skriver en klient-sida Swing-applikation (grafisk typsnittsdesigner) på Java 5. Nyligen har jag stött på java.lang.OutOfMemoryError: Java heap space"-fel eftersom jag inte är försiktig med minnesanvändningen. Användaren kan öppna ett obegränsat antal filer och programmet behåller de öppnade objekten i minnet. Efter en snabb sökning hittade jag [Ergonomics in the 5.0 Java Virtual Machine][1] och andra som säger att på Windows-maskiner är JVM:s standardvärde för maximal heap-storlek64MB`.

Hur ska jag hantera denna begränsning i denna situation?

Jag skulle kunna öka max heap size med hjälp av kommandoradsalternativet i java, men det skulle kräva att jag räknar ut tillgängligt RAM-minne och skriver något startprogram eller skript. Att öka till ett ändligt maxvärde gör dessutom inte slutligt att problemet försvinner.

Jag skulle kunna skriva om en del av min kod så att objekten ofta lagras i filsystemet (att använda en databas är samma sak) för att frigöra minnet. Det skulle kunna fungera, men det är förmodligen mycket arbete också.

Om du kan peka mig på detaljer om ovanstående idéer eller några alternativ som automatiskt virtuellt minne, dynamisk utökning av heapstorleken, skulle det vara bra.

Lösning

I slutändan har du alltid ett begränsat maximalt antal heap-filer att använda, oavsett vilken plattform du kör på. I Windows 32 bit är detta cirka 2 GB (inte specifikt heap utan den totala mängden minne per process). Det råkar bara vara så att Java väljer att göra standardvärdet mindre (förmodligen för att programmeraren inte skall kunna skapa program som har en galopperande minnesallokering utan att stöta på detta problem och behöva undersöka exakt vad de gör).

Så detta givet finns det flera tillvägagångssätt som du kan använda för att antingen bestämma vilken mängd minne du behöver eller för att minska den mängd minne du använder. Ett vanligt misstag med skräpinsamlade språk som Java eller C# är att behålla referenser till objekt som man inte längre använder, eller att allokera många objekt när man skulle kunna återanvända dem i stället. Så länge objekt har en referens till sig kommer de att fortsätta att använda utrymme på högen eftersom skräpplockaren inte raderar dem.

I det här fallet kan du använda en Java memory profiler för att avgöra vilka metoder i ditt program som allokerar ett stort antal objekt och sedan avgöra om det finns ett sätt att se till att de inte längre refereras, eller att inte allokera dem överhuvudtaget. Ett alternativ som jag har använt tidigare är "JMP" .

Om du fastställer att du allokerar dessa objekt av en anledning och att du behöver behålla referenser (beroende på vad du gör kan detta vara fallet), behöver du bara öka den maximala heapstorleken när du startar programmet. När du väl har gjort minnesprofileringen och förstått hur dina objekt allokeras bör du dock få en bättre uppfattning om hur mycket minne du behöver.

I allmänhet kommer du alltid att stöta på detta problem om du inte kan garantera att ditt program kommer att köras på en viss begränsad mängd minne (kanske beroende på ingångsstorleken). Det är först när du har uttömt allt detta som du behöver titta på caching av objekt på disk etc. Vid denna tidpunkt bör du ha en mycket god anledning att säga "Jag behöver Xgb minne" för något och du kan inte komma runt det genom att förbättra dina algoritmer eller minnesallokeringsmönster. I allmänhet gäller detta endast algoritmer som arbetar med stora datamängder (t.ex. en databas eller ett vetenskapligt analysprogram) och då blir tekniker som caching och memory mapped IO användbara.

Kommentarer (1)

Kör Java med kommandoradsalternativet -Xmx, som anger maximal storlek på heap.

[Se här för mer information] (http://docs.oracle.com/javase/7/docs/technotes/tools/windows/java.html#nonstandard).

Kommentarer (3)

Ja, med -Xmx kan du konfigurera mer minne för din JVM. För att vara säker på att du inte läcker eller slösar bort minne. Gör en heap dump och använd Eclipse Memory Analyzer för att analysera din minnesförbrukning.

Kommentarer (1)