Как бороться с ошибкой «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 ]

7 голосов
/ 17 августа 2010

Я читал где-то еще, что вы можете попробовать - поймать java.lang.OutOfMemoryError и в блоке catch вы можете освободить все ресурсы, которые, как вы знаете, могут использовать много памяти, закрыть соединения и т. Д., Затем выполнить System.gc() затем повторите то, что вы собирались сделать.

Другой способ заключается в том, что, хотя я не знаю, сработает ли это, но я сейчас проверяю, сработает ли оно в моем приложении.

Идея состоит в том, чтобы выполнить сборку мусора, вызвав System.gc (), который, как известно, увеличивает свободную память. Вы можете продолжать проверять это после того, как исполняется код памяти.

//Mimimum acceptable free memory you think your app needs
long minRunningMemory = (1024*1024);

Runtime runtime = Runtime.getRuntime();

if(runtime.freeMemory()<minRunningMemory)
 System.gc();
7 голосов
/ 09 октября 2008

Если вам необходимо отслеживать использование памяти во время выполнения, пакет java.lang.management предлагает MBeans, который можно использовать для мониторинга пулов памяти в вашей виртуальной машине (например, пространства eden, генерации с постоянным доступом и т. Д.), А также сбора мусора поведение.

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

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

7 голосов
/ 10 мая 2011

Я столкнулся с той же проблемой из-за размера кучи Java.

У меня есть два решения, если вы используете Java 5 (1.5).

  1. просто установите jdk1.6 и перейдите в настройки eclipse и установите путь jre jav1 1.6, как вы установили.

  2. Проверьте аргумент вашей виртуальной машины и пусть он будет таким, какой он есть. просто добавьте одну строку ниже всех аргументов, присутствующих в аргументах VM, как -Xms512m -Xmx512m -XX: MaxPermSize = ... м (192 м).

Я думаю, что это будет работать ...

7 голосов
/ 26 мая 2016

По умолчанию для разработки JVM использует небольшой размер и небольшую конфигурацию для других функций, связанных с производительностью. Но для производства вы можете настроить, например, (Кроме того, может существовать специальная конфигурация сервера приложений) -> (Если памяти все еще недостаточно для удовлетворения запроса, и куча уже достигла максимального размера, произойдет ошибка OutOfMemoryError)

-Xms<size>        set initial Java heap size
-Xmx<size>        set maximum Java heap size
-Xss<size>        set java thread stack size

-XX:ParallelGCThreads=8
-XX:+CMSClassUnloadingEnabled
-XX:InitiatingHeapOccupancyPercent=70
-XX:+UnlockDiagnosticVMOptions
-XX:+UseConcMarkSweepGC
-Xms512m
-Xmx8192m
-XX:MaxPermSize=256m (in java 8 optional)

Например: на платформе linux для производственного режима предпочтительные настройки.

После загрузки и настройки сервера таким способом http://www.ehowstuff.com/how-to-install-and-setup-apache-tomcat-8-on-centos-7-1-rhel-7/

1.создать файл setenv.sh в папке / opt / tomcat / bin /

   touch /opt/tomcat/bin/setenv.sh

2.Откройте и запишите эти параметры для настройки предпочтительного режима.

nano  /opt/tomcat/bin/setenv.sh 

export CATALINA_OPTS="$CATALINA_OPTS -XX:ParallelGCThreads=8"
export CATALINA_OPTS="$CATALINA_OPTS -XX:+CMSClassUnloadingEnabled"
export CATALINA_OPTS="$CATALINA_OPTS -XX:InitiatingHeapOccupancyPercent=70"
export CATALINA_OPTS="$CATALINA_OPTS -XX:+UnlockDiagnosticVMOptions"
export CATALINA_OPTS="$CATALINA_OPTS -XX:+UseConcMarkSweepGC"
export CATALINA_OPTS="$CATALINA_OPTS -Xms512m"
export CATALINA_OPTS="$CATALINA_OPTS -Xmx8192m"
export CATALINA_OPTS="$CATALINA_OPTS -XX:MaxMetaspaceSize=256M"

3. service tomcat restart

Обратите внимание, что JVM использует больше памяти, чем просто кучу. Например Методы Java, стеки потоков и собственные дескрипторы размещаются в памяти отдельно от кучи, а также внутренних структур данных JVM.

5 голосов
/ 19 мая 2009

Обратите внимание, что если вам это нужно в ситуации развертывания, рассмотрите возможность использования Java WebStart (с версией «ondisk», а не с сетевой - возможно в Java 6u10 и более поздних версиях), поскольку это позволяет вам указывать различные аргументы JVM кросс-платформенным способом.

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

1 голос
/ 13 июня 2017

Что касается NetBeans, вы можете установить максимальный размер кучи для решения проблемы.

Перейдите в «Выполнить», затем -> «Установить конфигурацию проекта» -> «Настроить» -> «Выполнить» его всплывающего окна -> «Вариант VM» -> заполнить «-Xms2048m -Xmx2048m.

1 голос
/ 04 апреля 2017

Если эта проблема возникает в Wildfly 8 и JDK1.8, тогда нам нужно указать настройки MaxMetaSpace вместо настроек PermGen.

Например, нам нужно добавить конфигурацию ниже в файле setenv.sh wildfly. JAVA_OPTS="$JAVA_OPTS -XX:MaxMetaspaceSize=256M"

Для получения дополнительной информации, пожалуйста, проверьте Проблема кучи Wildfly

1 голос
/ 29 сентября 2010

Если вы продолжаете выделять и хранить ссылки на объект, вы будете заполнять любой объем памяти, который у вас есть.

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

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

Ваша идея динамического расширения виртуальной памяти не решает проблему, поскольку машина ограничена в ресурсах, поэтому вы должны быть осторожны и решать проблемы с памятью (или, по крайней мере, быть осторожными с ними). ​​

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

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

-> Возможно, использование коллекций со слабыми ссылками (weakhashmap ...) может помочь с проблемами памяти, но вы должны быть осторожными с этим, так как вы можете обнаружить, что объект, который вы ищете, имеет было собрано.

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

...