Hvordan håndtere "java.lang.OutOfMemoryError: Java heap space" feil?

Jeg skriver en Swing-applikasjon på klientsiden (grafisk fontdesigner) på Java 5. Nylig kjører jeg inn i java.lang.OutOfMemoryError: Java heap space feil fordi jeg ikke er konservativ på minnebruk. Brukeren kan åpne ubegrenset antall filer, og programmet holder de åpnede objektene i minnet. Etter en rask undersøkelse fant jeg Ergonomics in the 5.0 Java Virtual Machine og andre som sier at på Windows-maskiner er JVM standard maks heapstørrelse som 64MB.

Gitt denne situasjonen, hvordan skal jeg håndtere denne begrensningen?

Jeg kunne øke maks bunke størrelse ved hjelp av kommandolinje alternativet til java, men det ville kreve å finne ut tilgjengelig RAM og skrive noe lanseringsprogram eller skript. Dessuten, å øke til en endelig maks, blir ikke til slutt kvitt problemet.

Jeg kunne omskrive noe av koden min for å vedvare objekter til filsystemet ofte (bruk av database er det samme) for å frigjøre minnet. Det kan fungere, men det er sannsynligvis mye arbeid også.

Hvis du kan peke meg på detaljer om ideene ovenfor eller noen alternativer som automatisk virtuelt minne, utvide haugstørrelsen dynamisk , vil det være flott.

Løsning

Til syvende og sist har du alltid en begrenset mengde heap å bruke uansett hvilken plattform du kjører på. I Windows 32 bit er dette rundt 2GB (ikke spesifikt heap, men total mengde minne per prosess). Det skjer bare at Java velger å gjøre standard mindre (antagelig slik at programmereren ikke kan lage programmer som har løpsk minneallokering uten å løpe inn i dette problemet og måtte undersøke nøyaktig hva de gjør).

Så dette gitt at det er flere tilnærminger du kan ta for å enten bestemme hvilken mengde minne du trenger eller for å redusere mengden minne du bruker. En vanlig feil med søppeloppsamlede språk som Java eller C# er å holde rundt referanser til objekter som du ikke lenger bruker, eller tildele mange objekter når du kunne gjenbruke dem i stedet. Så lenge objekter har en referanse til dem, vil de fortsette å bruke haugplass ettersom søppelsamleren ikke vil slette dem.

I dette tilfellet kan du bruke en Java-minneprofil for å finne ut hvilke metoder i programmet ditt som tildeler et stort antall objekter og deretter avgjøre om det er en måte å sørge for at de ikke lenger refereres til, eller å ikke tildele dem i utgangspunktet. Et alternativ som jeg har brukt tidligere er "JMP" .

Hvis du bestemmer at du tildeler disse objektene av en grunn, og du trenger å holde rundt referanser (avhengig av hva du gjør, kan dette være tilfelle), trenger du bare å øke den maksimale haugstørrelsen når du starter programmet. Når du har gjort minneprofileringen og forstått hvordan objektene dine blir allokert, bør du imidlertid ha en bedre ide om hvor mye minne du trenger.

Generelt hvis du ikke kan garantere at programmet ditt vil kjøre i en begrenset mengde minne (kanskje avhengig av inndatastørrelse), vil du alltid støte på dette problemet. Først etter å ha uttømt alt dette må du se på caching-objekter ut til disk osv. På dette tidspunktet bør du ha en veldig god grunn til å si "Jeg trenger X GB minne" for noe, og du kan ikke omgå det ved å forbedre algoritmene eller minnetildelingsmønstrene dine. Vanligvis vil dette vanligvis bare være tilfelle for algoritmer som opererer på store datasett (som en database eller et vitenskapelig analyseprogram), og da blir teknikker som hurtigbufring og minnekartlagt IO nyttige.

Kommentarer (1)

Kjør Java med kommandolinjealternativet -Xmx, som angir den maksimale størrelsen på heapen.

Se her for detaljer.

Kommentarer (3)

Ja, med -Xmx kan du konfigurere mer minne for din JVM. For å være sikker på at du ikke lekker eller sløser med minne. Ta en heap dump og bruk Eclipse Memory Analyzer for å analysere minneforbruket ditt.

Kommentarer (1)