Kuidas käsitleda "java.lang.OutOfMemoryError: Java kuhja ruumi" viga?

Kirjutan kliendipoolset Swing rakendust (graafiline fontide kujundaja) Java 5 peal. Hiljuti olen sattunud java.lang.OutOfMemoryError: Java heap space viga, sest ma ei ole mälukasutuse suhtes konservatiivne. Kasutaja saab avada piiramatu arvu faile ja programm hoiab avatud objekte mälus. Pärast kiiret uurimist leidsin Ergonomics in the 5.0 Java Virtual Machine ja teised ütlevad, et Windows masinas on JVM-i vaikimisi maksimaalne heap size 64MB.

Arvestades seda olukorda, kuidas ma peaksin selle piiranguga toime tulema?

Ma võiksin suurendada max heap size kasutades command line optsiooni java, kuid see nõuaks olemasoleva RAM-i väljaselgitamist ja mõne käivitava programmi või skripti kirjutamist. Pealegi, suurendamine mingi määratu maksimumini ei vahesta probleemi.

Ma võiksin ümber kirjutada osa oma koodist, et objektid püsivad sageli failisüsteemis (andmebaasi kasutamine on sama asi), et vabastada mälu. See võiks töötada, kuid see'on ilmselt palju tööd ka.

Kui te saaksite mulle näidata ülaltoodud ideede üksikasju või mõnda alternatiivi, nagu automaatne virtuaalne mälu, kuhja suuruse dünaamiline laiendamine, oleks see suurepärane.

Lahendus

Lõppkokkuvõttes on teil alati piiratud maksimaalne kasutatav kuhja, olenemata sellest, millisel platvormil te töötate. Windows 32 bitis on see umbes 2GB (mitte konkreetselt kuhja, vaid kogu mälu ühe protsessi kohta). Lihtsalt juhtub, et Java otsustab teha vaikimisi väiksema (arvatavasti selleks, et programmeerija ei saaks luua programme, millel on runaway memory allocation ilma, et ta selle probleemiga kokku puutuks ja peaks täpselt uurima, mida ta teeb).

Nii et antud juhul on mitmeid lähenemisi, mida saab kasutada kas selleks, et määrata, kui palju mälu on vaja või selleks, et vähendada kasutatava mälu hulka. Üks tavaline viga prügikogumiskeeltes nagu Java või C# on hoida viiteid objektidele, mida sa enam ei kasuta, või eraldada palju objekte, kui sa võiksid neid hoopis kasutada. Niikaua kui objektidel on viide neile, kasutavad nad jätkuvalt kuhja ruumi, kuna prügikoguja ei kustuta neid.

Sellisel juhul võite kasutada Java mäluprofiili kasutajat, et teha kindlaks, millised meetodid teie programmis eraldavad suurel hulgal objekte, ja seejärel teha kindlaks, kas on võimalik tagada, et neile enam ei viidata või et neid üldse ei eraldata. Üks võimalus, mida ma olen varem kasutanud, on "JMP" .

Kui te otsustate, et te eraldate neid objekte mingil põhjusel ja teil on vaja hoida viited ümber (sõltuvalt sellest, mida te teete, võib see olla nii), peate lihtsalt suurendama maksimaalset kuhja suurust programmi käivitamisel. Kui teete aga mäluprofiili ja mõistate, kuidas teie objektid eraldatakse, peaks teil olema parem ettekujutus sellest, kui palju mälu te vajate.

Üldiselt, kui te ei saa garanteerida, et teie programm töötab mingi piiratud mahuga mälus (võib-olla sõltuvalt sisendi suurusest), siis puutute alati kokku selle probleemiga. Alles pärast kõige selle ammendamist peate vaatama objektide vahemälu salvestamist kettale jne. Sel hetkel peaks teil olema väga hea põhjus öelda "mul on vaja Xgb mälu" millegi jaoks ja te ei saa'seda oma algoritme või mälu jaotamise mustreid parandades ümber teha. Üldiselt on see tavaliselt nii ainult suurte andmekogumitega (näiteks andmebaas või mõni teaduslik analüüsiprogramm) töötavate algoritmide puhul ja siis muutuvad kasulikuks sellised tehnikad nagu vahemälu ja mälu kaardistamise IO (memory mapped IO).

Kommentaarid (1)

Käivitage Java koos käsurea valikuga -Xmx, mis määrab maksimaalse kuhja suuruse.

Vaata siit täpsemalt.

Kommentaarid (3)

Jah, -Xmx abil saate oma JVM-i jaoks rohkem mälu konfigureerida. Et olla kindel, et te ei leki ega raiska mälu. Võtke kuhjumi dump ja kasutage Eclipse Memory Analyzer, et analüüsida oma mälutarbimist.

Kommentaarid (1)