Miten käsitellä "java.lang.OutOfMemoryError:" -virhe?

Kirjoitan asiakaspuolen Swing-sovellusta (graafinen fonttien suunnittelija) Java 5:llä. Viime aikoina olen törmännyt java.lang.OutOfMemoryError: Java heap space -virhe, koska en ole varovainen muistin käytön suhteen. Käyttäjä voi avata rajattoman määrän tiedostoja, ja ohjelma pitää avatut objektit muistissa. Pikaisen tutkimuksen jälkeen löysin Ergonomics in the 5.0 Java Virtual Machine ja muita, jotka sanovat, että Windows-koneessa JVM:n oletusarvona on maksimi heap size 64MB.

Miten minun pitäisi käsitellä tätä rajoitusta tässä tilanteessa?

Voisin lisätä max heap size -arvoa command line -vaihtoehdolla javaan, mutta se edellyttäisi käytettävissä olevan RAM-muistin selvittämistä ja jonkin käynnistysohjelman tai skriptin kirjoittamista. Sitä paitsi suurentaminen johonkin äärettömään maksimikokoon ei viimeisesti poista ongelmaa.

Voisin kirjoittaa osan koodistani uudelleen siten, että objektit tallennetaan usein tiedostojärjestelmään (tietokannan käyttö on sama asia), jotta muistia vapautuisi. Se voisi toimia, mutta se on luultavasti myös paljon työtä.

Jos voisit osoittaa minulle yksityiskohtia edellä mainituista ideoista tai vaihtoehdoista, kuten automaattisesta virtuaalimuistista, kasan koon laajentamisesta dynaamisesti, se olisi hienoa.

Ratkaisu

Loppujen lopuksi sinulla on aina rajallinen enimmäismäärä kasaa käytettävänäsi riippumatta siitä, millä alustalla käytät. Windows 32-bittisessä järjestelmässä tämä on noin 2 Gt (ei erityisesti kasa vaan prosessikohtainen kokonaismuistimäärä). Java vain sattuu tekemään oletusarvosta pienemmän (oletettavasti siksi, että ohjelmoijat eivät voi luoda ohjelmia, joissa muistinjako on karannut käsistä, törmäämättä tähän ongelmaan ja joutumatta tutkimaan tarkkaan, mitä he tekevät).

Joten tämä huomioon ottaen on olemassa useita lähestymistapoja, joita voit käyttää joko sen määrittämiseksi, kuinka paljon muistia tarvitset, tai käyttämäsi muistin määrän vähentämiseksi. Yksi yleinen virhe Javan ja C#:n kaltaisissa roskienkeräilykielissä on säilyttää viittauksia objekteihin, joita ei enää käytetä, tai varata paljon objekteja, vaikka niitä voisi käyttää uudelleen. Niin kauan kuin objekteihin viitataan, ne käyttävät edelleen kasan tilaa, sillä roskienkerääjä ei poista niitä.

Tässä tapauksessa voit käyttää Java-muistiprofiloijaa määrittääksesi, mitkä ohjelmasi metodit varaavat suuren määrän objekteja, ja selvittääksesi sitten, onko olemassa keino varmistaa, että niihin ei enää viitata, tai olla varaamatta niitä alun alkaenkaan. Yksi vaihtoehto, jota olen aiemmin käyttänyt, on "JMP" .

Jos huomaat, että allokoit näitä objekteja jostain syystä ja sinun on pidettävä viittaukset tallessa (riippuen siitä, mitä olet tekemässä, näin voi olla), sinun on vain kasvatettava kasan enimmäiskokoa, kun käynnistät ohjelman. Kun kuitenkin teet muistiprofiloinnin ja ymmärrät, miten objekteja allokoidaan, sinulla pitäisi olla parempi käsitys siitä, kuinka paljon muistia tarvitset.

Yleisesti ottaen, jos et voi taata, että ohjelmasi toimii jossakin rajallisessa määrässä muistia (ehkä riippuen syötteen koosta), törmäät aina tähän ongelmaan. Vasta kun olet käyttänyt kaiken tämän loppuun, sinun on tutkittava objektien välimuistiin tallentamista levylle jne. Tässä vaiheessa sinulla pitäisi olla erittäin hyvä syy sanoa "tarvitsen X gigatavua muistia" johonkin, etkä voi kiertää sitä parantamalla algoritmejasi tai muistinjakomalleja. Yleensä tämä pätee vain algoritmeihin, jotka toimivat suurilla datajoukoilla (kuten tietokannalla tai tieteellisellä analyysiohjelmalla), ja silloin välimuistitallennuksen ja muistikartoitetun tiedonsiirron kaltaiset tekniikat tulevat hyödyllisiksi.

Kommentit (1)

Suorita Java komentorivioptiolla -Xmx, joka asettaa kasan maksimikoon.

Katso lisätietoja täältä.

Kommentit (3)

Kyllä, -Xmx:n avulla voit määrittää lisää muistia JVM:lle. Varmistaaksesi, ettet vuoda tai tuhlaa muistia. Ota heap dump ja käytä Eclipsen muistianalysaattoria analysoidaksesi muistin kulutusta.

Kommentit (1)