Sådan håndteres "java.lang.OutOfMemoryError: Java heap space" fejl?

Jeg er ved at skrive et klient-side Swing-program (grafisk skrifttypedesigner) på Java 5. For nylig er jeg løbet ind i java.lang.OutOfMemoryError: Java heap space"-fejl, fordi jeg ikke er konservativ med hensyn til hukommelsesforbrug. Brugeren kan åbne et ubegrænset antal filer, og programmet beholder de åbnede objekter i hukommelsen. Efter en hurtig undersøgelse fandt jeg [Ergonomics in the 5.0 Java Virtual Machine][1] og andre, der siger, at på Windows-maskinen er JVM'en standardiseret som max heap-størrelse på64MB`.

Hvordan skal jeg i denne situation håndtere denne begrænsning?

Jeg kunne øge max heap size ved hjælp af command line option til java, men det ville kræve, at jeg fandt ud af, hvor meget RAM der er til rådighed, og at jeg skrev et program eller script til at starte programmet. Desuden er en forøgelse til et uendeligt maksimum ikke ultimeligt nok til at løse problemet.

Jeg kunne omskrive noget af min kode til at persistere objekter til filsystemet ofte (ved hjælp af database er det samme) for at frigøre hukommelsen. Det kunne virke, men det'er nok også en masse arbejde.

Hvis du kunne pege mig på detaljer om ovenstående ideer eller nogle alternativer som automatisk virtuel hukommelse, udvidelse af heap-størrelse dynamisk, ville det være fantastisk.

Løsning

I sidste ende har du altid et begrænset maksimum af heap, som du kan bruge, uanset hvilken platform du kører på. I Windows 32 bit er dette omkring 2GB (ikke specifikt heap, men den samlede mængde hukommelse pr. proces). Det sker bare, at Java vælger at gøre standardværdien mindre (formentlig for at programmøren ikke kan lave programmer med løbsk hukommelsesallokering uden at løbe ind i dette problem og være nødt til at undersøge præcis, hvad de gør).

Så dette givet er der flere tilgange du kan tage for enten at bestemme hvilken mængde hukommelse du har brug for eller for at reducere den mængde hukommelse du bruger. En almindelig fejl med garbage collected-sprog som Java eller C# er at beholde referencer til objekter, som man ikke længere bruger, eller at allokere mange objekter, når man kunne genbruge dem i stedet. Så længe objekter har en reference til dem, vil de fortsætte med at bruge heap-plads, da garbage collector ikke sletter dem.

I dette tilfælde kan du bruge en Java-hukommelsesprofiler til at bestemme, hvilke metoder i dit program der allokerer mange objekter, og derefter bestemme, om der er en måde at sikre, at de ikke længere refereres, eller om du kan lade være med at allokere dem i det hele taget. En mulighed, som jeg tidligere har brugt, er "JMP" .

Hvis du konstaterer, at du allokerer disse objekter af en grund, og at du har brug for at beholde referencerne (afhængigt af hvad du laver, kan det være tilfældet), skal du blot øge den maksimale heapstørrelse, når du starter programmet. Men når du først har lavet hukommelsesprofileringen og forstået, hvordan dine objekter bliver allokeret, burde du have en bedre idé om, hvor meget hukommelse du har brug for.

Generelt vil du altid løbe ind i dette problem, hvis du ikke kan garantere, at dit program vil køre på en eller anden begrænset mængde hukommelse (måske afhængigt af inputstørrelsen). Først når du har udtømt alt dette, skal du se på caching af objekter ud på disk osv. På dette tidspunkt bør du have en meget god grund til at sige "Jeg har brug for Xgb hukommelse" til noget, og du kan ikke arbejde udenom det ved at forbedre dine algoritmer eller hukommelsesallokeringsmønstre. Generelt vil dette normalt kun være tilfældet for algoritmer, der opererer på store datasæt (som en database eller et videnskabeligt analyseprogram), og så bliver teknikker som caching og memory mapped IO nyttige.

Kommentarer (1)

Kør Java med kommandolinjeindstillingen -Xmx, som sætter maksimal størrelse på heap'en.

[Se her for detaljer] (http://docs.oracle.com/javase/7/docs/technotes/tools/windows/java.html#nonstandard).

Kommentarer (3)

Ja, med -Xmx kan du konfigurere mere hukommelse til din JVM. For at være sikker på, at du ikke lækker eller spilder hukommelse. Tag et heap dump og brug Eclipse Memory Analyzer til at analysere dit hukommelsesforbrug.

Kommentarer (1)