Hoe om te gaan met "java.lang.OutOfMemoryError: Java heap space" fout?

Ik schrijf een client-side Swing applicatie (grafische font ontwerper) op Java 5. Onlangs, loop ik tegen java.lang.OutOfMemoryError: Java heap space fout omdat ik niet voorzichtig ben met geheugengebruik. De gebruiker kan een onbeperkt aantal bestanden openen, en het programma houdt de geopende objecten in het geheugen. Na een snel onderzoek vond ik Ergonomics in the 5.0 Java Virtual Machine en anderen die zeggen dat op een Windows machine de JVM standaard een maximale heap grootte heeft van 64MB.

Gezien deze situatie, hoe moet ik omgaan met deze beperking?

Ik zou de max heap size kunnen verhogen door gebruik te maken van de command line optie van java, maar dat zou vereisen dat ik uitzoek hoeveel RAM beschikbaar is en dat ik een programma of script moet schrijven. Bovendien, het verhogen van de heap tot een of ander eindig maximum zal het probleem niet uiteindelijk verhelpen.

Ik zou een deel van mijn code kunnen herschrijven om objecten regelmatig naar het bestandssysteem te persisteren (een database gebruiken is hetzelfde) om geheugen vrij te maken. Het zou kunnen werken, maar het'is waarschijnlijk ook veel werk.

Als je me zou kunnen wijzen op details van bovenstaande ideeën of alternatieven zoals automatisch virtueel geheugen, dynamisch uitbreiden van heap grootte, zou dat geweldig zijn.

Oplossing

Uiteindelijk heb je altijd een eindige heap die je kunt gebruiken, ongeacht op welk platform je draait. In Windows 32 bit is dit ongeveer 2GB (niet specifiek heap maar totale hoeveelheid geheugen per proces). Het toeval wil dat Java ervoor kiest om de standaard kleiner te maken (vermoedelijk zodat de programmeur geen programma's kan maken die op hol geslagen geheugen allocatie hebben zonder tegen dit probleem aan te lopen en te moeten onderzoeken wat ze precies aan het doen zijn).

Dus dit gegeven zijn er verschillende benaderingen die je zou kunnen nemen om ofwel te bepalen welke hoeveelheid geheugen je nodig hebt of om de hoeveelheid geheugen die je gebruikt te verkleinen. Een veelgemaakte fout met garbage collected talen zoals Java of C# is het rondslingeren van referenties naar objecten die je niet langer gebruikt, of het toewijzen van veel objecten terwijl je ze in plaats daarvan zou kunnen hergebruiken. Zolang objecten een referentie hebben, zullen ze heapruimte blijven gebruiken omdat de garbage collector ze niet zal verwijderen.

In dit geval kun je een Java geheugen profiler gebruiken om te bepalen welke methodes in je programma grote aantallen objecten toewijzen en dan bepalen of er een manier is om ervoor te zorgen dat er niet langer naar verwezen wordt, of om ze in de eerste plaats niet toe te wijzen. Een optie die ik in het verleden heb gebruikt is "JMP" .

Als je vaststelt dat je deze objecten om een reden toewijst en dat je verwijzingen nodig hebt (afhankelijk van wat je aan het doen bent kan dit het geval zijn), dan hoef je alleen maar de max heap grootte te verhogen als je het programma start. Echter, als je eenmaal geheugenprofilering doet en begrijpt hoe je objecten gealloceerd worden, zou je een beter idee moeten hebben over hoeveel geheugen je nodig hebt.

In het algemeen als je niet kunt garanderen dat je programma zal draaien in een eindige hoeveelheid geheugen (misschien afhankelijk van de grootte van de invoer) zul je altijd tegen dit probleem aanlopen. Pas als je dit allemaal hebt uitgeput, zul je moeten kijken naar het cachen van objecten op schijf enz. Op dit punt zou je een zeer goede reden moeten hebben om te zeggen "Ik heb Xgb geheugen nodig" voor iets en je kunt er niet'omheen werken door je algoritmes of geheugentoewijzingspatronen te verbeteren. Over het algemeen zal dit alleen het geval zijn voor algoritmen die werken op grote datasets (zoals een database of een of ander wetenschappelijk analyseprogramma) en dan worden technieken als caching en memory mapped IO nuttig.

Commentaren (1)

Start Java met de command-line optie -Xmx, die de maximale grootte van de heap instelt.

Zie hier voor details.

Commentaren (3)

Ja, met -Xmx kun je meer geheugen configureren voor je JVM. Om zeker te zijn dat je geen geheugen lekt of verspilt. Neem een heap dump en gebruik de Eclipse Memory Analyzer om je geheugengebruik te analyseren.

Commentaren (1)