Как бороться с " java.ленг.Ошибка "OutOfMemoryError: Java heap space" (размер кучи 64 МБ)

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

учитывая эту ситуацию, как я должен бороться с этим ограничением?

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

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

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

18 ответов


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

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

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

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

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


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

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


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

вслед за Затмение Гелиос/Юнона/Кеплер:

Правой Кнопкой Мыши на

 Run As - Run Configuration - Arguments - Vm Arguments, 

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

-Xmx2048m

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

  1. использовать локальные переменные везде, где это возможно.
  2. убедитесь, что вы выбрали правильный объект (например, выбор между string, StringBuffer и StringBuilder)
  3. используйте хорошую систему кода для вашей программы (например: использование статических переменных против нестатических переменных)
  4. прочее что может сработать с вашим кодом.
  5. попробуйте двигаться с Multy THREADING

большая оговорка - - - - в моем офисе мы обнаружили, что (на некоторых машинах windows) мы не могли выделить более 512m для кучи Java. Это оказалось связано с антивирусным продуктом Kaspersky, установленным на некоторых из этих машин. После удаления этого AV-продукта мы обнаружили, что можем выделить по крайней мере 1.6 gb, i.e, - Xmx1600m (M обязательно, иначе это приведет к другой ошибке "слишком маленькая начальная куча") работает.

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


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

на Run --> Run Configurations --> выберите проект под сборка --> перейдите на вкладку "версии" --> введите -Xmx1024m.

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

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


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


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

исключение в потоке thread_name:java.ленг.OutOfMemoryError: пространство кучи Java

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

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

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

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

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

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

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

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


выполните следующие действия:

  1. открыть catalina.sh из tomcat / bin.

  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. перезапустите tomcat


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

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

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

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

Runtime runtime = Runtime.getRuntime();

if(runtime.freeMemory()<minRunningMemory)
 System.gc();

Я столкнулся с той же проблемой размера кучи java. У меня есть два решения, если вы используете Java 5(1.5).

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

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

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


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

вот пример увеличения максимального размера кучи JVM, также лучше сохранить-Xmx в-xms рацион либо 1: 1, либо 1: 1.5, если вы устанавливаете размер кучи в приложении java.

export JVM_ARGS="-Xms1024m -Xmx1024m"

Ссылка


Если вам нужно контролировать использование памяти во время выполнения, java.ленг.пакет управления предлагает MBeans, которые можно использовать для мониторинга пулов памяти в вашей виртуальной машине (например, eden space, tenured generation и т. д.), а также поведения сборки мусора.

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

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


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

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


по умолчанию для разработки 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.


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

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

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

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

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

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

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

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


Что касается netbeans, вы можете установить максимальный размер кучи для решения проблемы. Во-первых, перейдите в "Выполнить", затем- > "настройка конфигурации проекта" - > "настройка" - > "запуск" его всплывающего окна - > "опция VM" - > заполните "- Xms2048m-Xmx2048m".


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

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

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