Вопрос

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

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

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

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

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

Это было полезно?

Решение

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

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

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

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

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

Другие советы

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

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

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

Ниже приводится описание Eclipse Helios / Juno / Kepler :

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

 Run As - Run Configuration - Arguments - Vm Arguments, 

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

-Xmx2048m

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

<Ол>
  • Используйте локальные переменные везде, где это возможно.
  • Убедитесь, что вы выбрали правильный объект (например, выбор между String, StringBuffer и StringBuilder)
  • Используйте хорошую систему кодирования для вашей программы (пример: использование статических переменных против не статических переменных)
  • Другие вещи, которые могут работать с вашим кодом.
  • Попытайтесь двигаться с помощью многозаходной резьбы
  • Большое предостережение ---- в моем офисе мы обнаружили, что (на некоторых компьютерах с Windows) мы не можем выделить более 512 м для кучи Java. Это связано с тем, что на некоторых из этих компьютеров установлен антивирус Касперского. После удаления этого продукта AV мы обнаружили, что можем выделить как минимум 1,6 ГБ, т. Е. -Xmx1600m (m обязательно, в противном случае это приведет к другой ошибке «Слишком маленькая начальная куча»).

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

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

    перейдите в Run - > Запустите настройки - > , затем выберите проект в maven build - > затем выберите вкладку «JRE»; - & GT; затем введите -Xmx1024m .

    В качестве альтернативы вы можете выполнить Run - > Запустить настройки - > выберите " JRE " вкладка - > , затем введите - Xmx1024m

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

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

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

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

      

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

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

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

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

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

  •   

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

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

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

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

    <Ол>
  • Откройте catalina.sh из tomcat / bin.

  • Измените 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"
    
  • Перезагрузите кота

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

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

    export JVM_ARGS = " -Xms1024m -Xmx1024m "

    Ссылочная ссылка

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

      

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

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

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

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

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

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

    Я читал где-то еще, что вы можете попробовать - поймать 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();
    

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

    Лицензировано под: CC-BY-SA с атрибуция
    Не связан с StackOverflow
    scroll top