Как бороться с ошибкой «java.lang.OutOfMemoryError: Java heap space»? - PullRequest
365 голосов
/ 01 сентября 2008

Я пишу клиентское приложение Swing (графический дизайнер шрифтов) на Java 5 . В последнее время я сталкиваюсь с ошибкой java.lang.OutOfMemoryError: Java heap space, потому что я не консервативен в использовании памяти. Пользователь может открывать неограниченное количество файлов, а программа сохраняет открытые объекты в памяти. После быстрого исследования я обнаружил эргономику в виртуальной машине Java 5.0 и другие говорят, что на машине Windows JVM по умолчанию устанавливает максимальный размер кучи как 64MB.

Учитывая эту ситуацию, как мне справиться с этим ограничением?

Я мог бы увеличить максимальный размер кучи , используя параметр командной строки для java, но для этого потребовалось бы выяснить доступную ОЗУ и написать какую-нибудь запускающую программу или скрипт. Кроме того, увеличение до некоторого конечного max не в конечном итоге избавит от проблемы.

Я мог бы переписать часть своего кода для частого сохранения объектов в файловой системе (использование базы данных - то же самое), чтобы освободить память. Это может сработать, но, вероятно, это тоже много работы.

Если бы вы могли указать мне на детали вышеупомянутых идей или некоторые альтернативы, такие как автоматическая виртуальная память, динамически увеличивая размер кучи , это было бы здорово.

Ответы [ 18 ]

222 голосов
/ 01 сентября 2008

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

Таким образом, учитывая, что есть несколько подходов, которые вы можете использовать, чтобы определить, какой объем памяти вам нужен, или уменьшить объем используемой памяти. Одной из распространенных ошибок в языках сборки мусора, таких как Java или C #, является сохранение ссылок на объекты, которые вы больше не используете , или выделение множества объектов, когда вместо них можно повторно использовать . Пока объекты имеют ссылку на них, они будут продолжать использовать пространство кучи, поскольку сборщик мусора не удалит их.

В этом случае вы можете использовать профилировщик памяти Java, чтобы определить, какие методы в вашей программе выделяют большое количество объектов, а затем определить, есть ли способ убедиться, что на них больше нет ссылок, или не выделять их в первое место. Одна из опций, которую я использовал в прошлом, это «JMP» http://www.khelekore.org/jmp/.

Если вы решите, что вы распределяете эти объекты по какой-то причине, и вам необходимо хранить ссылки (в зависимости от того, что вы делаете, это может иметь место), вам просто нужно увеличить максимальный размер кучи, когда вы запускаете программа. Однако, как только вы выполните профилирование памяти и поймете, как распределяются ваши объекты, у вас должно быть лучшее представление о том, сколько памяти вам нужно.

В общем, если вы не можете гарантировать, что ваша программа будет работать в ограниченном объеме памяти (возможно, в зависимости от размера ввода), вы всегда столкнетесь с этой проблемой. Только после исчерпания всего этого вам нужно будет изучить кэширование объектов на диск и т. Д. В этот момент у вас должна быть очень веская причина сказать «мне нужен Xgb памяти» для чего-то, и вы не сможете обойти это, улучшив ваши алгоритмы или шаблоны распределения памяти. Как правило, это будет иметь место только в случае алгоритмов, работающих с большими наборами данных (например, с базой данных или какой-либо программой научного анализа), и тогда становятся полезными такие методы, как кэширование и ввод-вывод в память.

110 голосов
/ 01 сентября 2008

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

Подробнее см. Здесь .

82 голосов
/ 25 февраля 2011

Вы можете указать для проекта, сколько кучи требует ваш проект

Следующее для Eclipse Helios / Juno / Kepler :

Клик правой кнопкой мыши на

 Run As - Run Configuration - Arguments - Vm Arguments, 

затем добавьте это

-Xmx2048m
38 голосов
/ 01 февраля 2014

Увеличение размера кучи - это не «исправление», это «штукатурка», 100% временная. Это снова рухнет в другом месте. Чтобы избежать этих проблем, напишите высокопроизводительный код.

  1. Используйте локальные переменные везде, где это возможно.
  2. Убедитесь, что вы выбрали правильный объект (например: Выбор между String, StringBuffer и StringBuilder)
  3. Используйте хорошую систему кодирования для вашей программы (например: Использование статических переменных против статических переменных)
  4. Другие вещи, которые могут работать с вашим кодом.
  5. Попробуй двигаться с МНОГО ФРЕЗКАМИ
31 голосов
/ 14 апреля 2009

Большое предостережение ---- в моем офисе мы обнаружили, что (на некоторых компьютерах с Windows) мы не можем выделить более 512 м для кучи Java. Это связано с тем, что на некоторых из этих компьютеров установлен антивирус Касперского. После удаления этого продукта AV мы обнаружили, что можем выделить как минимум 1,6 ГБ, т. Е. -Xmx1600m (в противном случае m обязательно; это приведет к другой ошибке «Слишком маленькая начальная куча»).

Не знаю, происходит ли это с другими AV-продуктами, но, вероятно, это происходит потому, что AV-программа резервирует небольшой блок памяти в каждом адресном пространстве, тем самым предотвращая одно действительно большое выделение.

20 голосов
/ 10 июня 2011

Аргументы VM работали для меня в Eclipse. Если вы используете eclipse версии 3.4, сделайте следующее

перейдите на Run --> Run Configurations -->, затем выберите проект в maven build ->, затем выберите вкладку "JRE" ->, затем введите -Xmx1024m.

В качестве альтернативы вы можете сделать Run --> Run Configurations --> select the "JRE" tab -->, затем ввести - Xmx1024m

Это должно увеличить кучу памяти для всех сборок / проектов. Приведенный выше объем памяти составляет 1 ГБ. Вы можете оптимизировать, как вы хотите.

16 голосов
/ 09 октября 2008

Да, с -Xmx вы можете настроить больше памяти для вашей JVM. Чтобы быть уверенным, что вы не утечки или тратить память. Возьмите дамп кучи и используйте Eclipse Memory Analyzer для анализа потребления памяти.

13 голосов
/ 22 марта 2016

Я бы хотел добавить рекомендации от оракула Устранение неисправностей Статья.

Исключение в потоке имя_потока: java.lang.OutOfMemoryError: Пространство кучи Java

Подробное сообщение пространство кучи Java указывает, что объект не может быть выделен в куче Java. Эта ошибка не обязательно означает утечку памяти

Возможные причины:

  1. Простая проблема конфигурации , когда указанный размер кучи недостаточен для приложения.

  2. Приложение непреднамеренно хранит ссылки на объекты , и это предотвращает сбор мусора для объектов.

  3. Чрезмерное использование финализаторов .

Еще один потенциальный источник этой ошибки возникает в приложениях, которые чрезмерно используют финализаторы. Если у класса есть метод finalize, то у объектов этого типа не освобождается пространство во время сборки мусора

После сборки мусора объекты ставятся в очередь для финализации , что происходит позже. финализаторы выполняются потоком демона, который обслуживает очередь завершения. Если поток finalizer не может идти в ногу с очередью завершения, то может заполниться куча Java и будет выдан исключительный тип OutOfMemoryError .

Один сценарий, который может вызвать эту ситуацию, - это когда приложение создает высокоприоритетные потоки , которые вызывают увеличение очереди финализация со скоростью, которая быстрее, чем скорость, с которой поток финализатора обслуживает эту очередь.

8 голосов
/ 07 октября 2013

Выполните следующие шаги:

  1. Открыть catalina.sh из кота / корзины.

  2. Изменить JAVA_OPTS на

    JAVA_OPTS="-Djava.awt.headless=true -Dfile.encoding=UTF-8 -server -Xms1536m 
    -Xmx1536m -XX:NewSize=256m -XX:MaxNewSize=256m -XX:PermSize=256m 
    -XX:MaxPermSize=256m -XX:+DisableExplicitGC"
    
  3. Перезагрузите кота

7 голосов
/ 04 сентября 2011

Простой способ решить OutOfMemoryError в Java - это увеличить максимальный размер кучи с помощью параметров JVM -Xmx512M, это немедленно решит вашу ошибку OutOfMemoryError. Это мое предпочтительное решение, когда я получаю OutOfMemoryError в Eclipse, Maven или ANT при построении проекта, потому что в зависимости от размера проекта вы можете легко исчерпать память.

Вот пример увеличения максимального размера кучи JVM. Также лучше сохранить соотношение -Xmx к -Xms 1: 1 или 1: 1,5, если вы устанавливаете размер кучи в своем Java-приложении.

export JVM_ARGS="-Xms1024m -Xmx1024m"

Ссылка на ссылку

...