Как да се справим с "java.lang.OutOfMemoryError: Java heap space" грешка?

Пиша клиентско приложение Swing (графичен дизайнер на шрифтове) на Java 5. Напоследък се сблъсквам с java.lang.OutOfMemoryError: Java heap space, защото не съм консервативен по отношение на използването на паметта. Потребителят може да отваря неограничен брой файлове и програмата запазва отворените обекти в паметта. След кратко проучване намерих Ergonomics in the 5.0 Java Virtual Machine и други, които казват, че на машина с Windows JVM по подразбиране максималният размер на купчината е 64MB.

При това положение как трябва да се справя с това ограничение?

Бих могъл да увелича максималния размер на купчината, като използвам опция от командния ред на Java, но това ще изисква да разбера наличната оперативна памет и да напиша някаква програма или скрипт за стартиране. Освен това увеличаването до някаква безкрайна максимална стойност не води до окончателно отстраняване на проблема.

Бих могъл да пренапиша част от кода си, за да запазвам обектите във файловата система често (използването на база данни е същото), за да освободя паметта. Това може да проработи, но вероятно е и много работа.

Ако можете да ме насочите към подробности за горните идеи или към някои алтернативи като автоматична виртуална памет, динамично разширяване на размера на купчината, това ще бъде чудесно.

Решение

В крайна сметка винаги разполагате с ограничена максимална куча памет, която да използвате, независимо на каква платформа работите. В Windows 32 bit това е около 2GB (не конкретно за купчината, а за общото количество памет за всеки процес). Просто се случва така, че Java решава да направи този размер по подразбиране по-малък (вероятно за да не може програмистът да създава програми, които имат бясно разпределение на паметта, без да се сблъсква с този проблем и да се налага да проверява какво точно прави).

Така че при това положение има няколко подхода, които бихте могли да предприемете, за да определите от какво количество памет се нуждаете или да намалите количеството памет, което използвате. Една често срещана грешка при езиците със събиране на боклука, като Java или C#, е да се поддържат референции към обекти, които вече не използвате, или да се заделят много обекти, когато вместо това бихте могли да ги използвате повторно. Докато обектите имат препратка към тях, те ще продължат да използват пространството на купчината, тъй като колекторът на боклука няма да ги изтрие.

В този случай можете да използвате Java профил на паметта, за да определите кои методи в програмата ви заделят голям брой обекти и след това да определите дали има начин да се уверите, че към тях вече няма препратки, или изобщо да не ги заделяте. Една възможност, която съм използвал в миналото, е "JMP" .

Ако установите, че заделяте тези обекти по някаква причина и трябва да запазите препратките към тях (в зависимост от това какво правите, това може да е така), просто ще трябва да увеличите максималния размер на купчината, когато стартирате програмата. Въпреки това, след като направите профилиране на паметта и разберете как се заделят вашите обекти, трябва да имате по-добра представа за това колко памет ви е необходима.

Като цяло, ако не можете да'гарантирате, че програмата ви ще работи в някакво крайно количество памет (може би в зависимост от размера на входа), винаги ще се сблъсквате с този проблем. Едва след като изчерпате всичко това, ще трябва да разгледате възможността за кеширане на обекти на диска и т.н. В този момент трябва да имате много добра причина да кажете "Имам нужда от Xgb памет" за нещо и не можете да го заобиколите, като подобрите алгоритмите си или моделите за разпределение на паметта. По принцип това се отнася само за алгоритми, работещи с големи масиви от данни (като база данни или програма за научен анализ), и тогава техники като кеширане и картографиране на входно-изходните операции в паметта стават полезни.

Коментари (1)

Стартирайте Java с опцията на командния ред -Xmx, която задава максималния размер на купчината.

Вижте тук за подробности.

Коментари (3)

Да, с помощта на -Xmx можете да конфигурирате повече памет за вашия JVM. За да сте сигурни, че няма да изпускате или разхищавате памет. Направете heap dump и използвайте Eclipse Memory Analyzer, за да анализирате потреблението на памет.

Коментари (1)