Píšem aplikáciu Swing na strane klienta (grafický návrhár písma) na Jave 5. V poslednom čase narážam na chybu java.lang.OutOfMemoryError: Chyba Java heap space
, pretože nie som konzervatívny vo využívaní pamäte. Používateľ môže otvoriť neobmedzený počet súborov a program si otvorené objekty uchováva v pamäti. Po rýchlom prieskume som našiel Ergonomics in the 5.0 Java Virtual Machine a ďalšie, ktoré hovoria, že na počítači s Windows je predvolená maximálna veľkosť haldy JVM 64 MB
.
Ako sa mám vzhľadom na túto situáciu vysporiadať s týmto obmedzením?
Mohol by som zvýšiť max heap size pomocou command line option to java, ale to by si vyžadovalo zistiť dostupnú RAM a napísať nejaký spúšťací program alebo skript. Okrem toho, zvýšenie na nejakú nekonečnú maximálnu hodnotu tento problém konečne neodstráni.
Mohol by som prepísať časť svojho kódu tak, aby objekty často perzistovali v súborovom systéme (použitie databázy je to isté) a uvoľnili tak pamäť. Mohlo by to fungovať, ale je to asi aj veľa práce.
Ak by ste ma mohli odkázať na detaily vyššie uvedených nápadov alebo na nejaké alternatívy, ako napríklad automatické rozšírenie virtuálnej pamäte, dynamické rozšírenie veľkosti haldy, bolo by to skvelé.
V konečnom dôsledku máte vždy k dispozícii maximálne množstvo haldy, ktoré môžete použiť, bez ohľadu na to, na akej platforme bežíte. V 32-bitovom systéme Windows je to približne 2 GB (nie konkrétne haldy, ale celkového množstva pamäte na proces). Jednoducho sa stáva, že Java sa rozhodne, že predvolená hodnota je menšia (pravdepodobne preto, aby programátor nemohol vytvárať programy, ktoré majú bežné prideľovanie pamäte bez toho, aby narazil na tento problém a musel skúmať, čo presne robí).
Takže vzhľadom na to existuje niekoľko prístupov, ktoré môžete použiť buď na určenie toho, aké množstvo pamäte potrebujete, alebo na zníženie množstva používanej pamäte. Jednou z častých chýb v jazykoch so zberom odpadu, ako sú Java alebo C#, je udržiavanie referencií na objekty, ktoré už nepoužívate, alebo alokovanie mnohých objektov, keď by ste ich namiesto toho mohli použiť. Pokiaľ majú objekty referenciu, budú naďalej využívať priestor na halde, pretože garbage collector ich neodstráni.
V tomto prípade môžete použiť profilovač pamäte Java na zistenie, ktoré metódy vo vašom programe alokujú veľké množstvo objektov, a potom určiť, či existuje spôsob, ako zabezpečiť, aby sa na ne už neodkazovalo, alebo ich vôbec nealokovať. Jednou z možností, ktorú som v minulosti použil, je "JMP" http://www.khelekore.org/jmp/.
Ak zistíte, že tieto objekty alokujete z nejakého dôvodu a potrebujete zachovať referencie (v závislosti od toho, čo robíte, to môže byť tento prípad), stačí pri spustení programu zvýšiť maximálnu veľkosť haldy. Keď však urobíte profilovanie pamäte a pochopíte, ako sa vaše objekty alokujú, mali by ste mať lepšiu predstavu o tom, koľko pamäte potrebujete.
Vo všeobecnosti, ak nemôžete zaručiť, že váš program bude bežať v nejakom konečnom množstve pamäte (možno v závislosti od veľkosti vstupu), vždy narazíte na tento problém. Až po vyčerpaní všetkých týchto možností sa budete musieť zaoberať ukladaním objektov do vyrovnávacej pamäte na disk atď. V tomto bode by ste mali mať veľmi dobrý dôvod povedať "Potrebujem Xgb pamäte" na niečo a nemôžete to obísť zlepšením svojich algoritmov alebo vzorov alokácie pamäte. Vo všeobecnosti to bude zvyčajne len v prípade algoritmov pracujúcich s veľkými súbormi údajov (ako je databáza alebo nejaký program na vedeckú analýzu) a vtedy sa stanú užitočnými techniky ako caching a mapovanie IO v pamäti.
Spustite Javu s voľbou príkazového riadka -Xmx
, ktorá nastaví maximálnu veľkosť haldy.
Áno, pomocou -Xmx
môžete nakonfigurovať viac pamäte pre svoj JVM.
Aby ste si boli istí, že nedôjde k úniku alebo plytvaniu pamäťou. Urobte výpis haldy a použite Eclipse Memory Analyzer na analýzu spotreby pamäte.