java.lang.OutOfMemoryError: пространство кучи Java


97

Я получаю следующую ошибку при выполнении многопоточной программы

java.lang.OutOfMemoryError: Java heap space

Вышеупомянутая ошибка произошла в одном из потоков.

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

  2. Есть ли способ увеличить объем кучи?

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


Ответы:


105

Если вы хотите увеличить пространство кучи, вы можете использовать его java -Xms<initial heap size> -Xmx<maximum heap size>в командной строке. По умолчанию значения основаны на версии JRE и конфигурации системы. Вы можете узнать больше о параметрах виртуальной машины на веб-сайте Java .

Однако я бы рекомендовал профилировать ваше приложение, чтобы узнать, почему ваш размер кучи съедается. NetBeans имеет очень хороший профилировщик . Я считаю, что он использует jvisualvmпод капотом. С помощью профилировщика вы можете попытаться найти, где создается много объектов, когда объекты собираются сборщиком мусора и т. Д.


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

Я добавил ссылку на страницу на сайте NetBeans ( profiler.netbeans.org ), на которой есть очень хорошая документация по профилю, от самых основ до более продвинутого использования.
Томас Оуэнс,

Значения по умолчанию меняются с версиями java, было бы неплохо включить эту информацию в свой ответ.
Дариуш

Просто исправил аналогичную проблему и сначала попробовал: java -jar Division.jar -Xmx512m -Xms512m - это дает мне ту же ошибку, но когда я делаю это так: java -Xmx512m -Xms512m -jar Division.jar - все в порядке. Так что порядок параметров также важен.
hipokito

@hipokito Аргументы после файла jar передаются методу main () файла jar как args []
Asu

29

1.- Да, но это в значительной степени относится ко всей памяти, используемой вашей программой.

2.- Да, см. Параметры Java VM

-Xms<size>        set initial Java heap size
-Xmx<size>        set maximum Java heap size

Т.е.

java -Xmx2g назначьте вашему приложению максимум 2 гигабайта оперативной памяти

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

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


while which (true);)
Гал Браха

8

Вы можете посетить этот сайт, чтобы узнать больше о памяти в JVM: http://developer.streamezzo.com/content/learn/articles/optimization-heap-memory-usage

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

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

Отлично! Я отдам JVM 1 ГБ ОЗУ.

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

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


6

Чтобы увеличить размер кучи, вы можете использовать аргумент -Xmx при запуске Java; например

-Xmx256M

6

Вы можете получить размер кучи с помощью приведенной ниже программы.

public class GetHeapSize {
    public static void main(String[] args) {
        long heapsize = Runtime.getRuntime().totalMemory();
        System.out.println("heapsize is :: " + heapsize);
    }
} 

соответственно, вы можете увеличить размер кучи, используя: java -Xmx2g http://www.oracle.com/technetwork/java/javase/tech/vmoptions-jsp-140102.html


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

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

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

  1. Есть ли способ увеличить объем кучи?

Да. Взгляните на эту статью о Oracle для получения более подробной информации.

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

-Xms:, который устанавливает начальный и минимальный размер кучи

-Xmx:, который устанавливает максимальный размер кучи

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

Это зависит от вашего приложения.

  1. Установите максимальную память кучи в соответствии с требованиями вашего приложения

  2. Не вызывайте утечки памяти в вашем приложении

  3. Если вы обнаружите утечки памяти в своем приложении, найдите основную причину с помощью инструментов профилирования, таких как MAT , Visual VM , jconsole и т. Д. Как только вы найдете основную причину, устраните утечки.

Важные примечания из статьи о Oracle

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

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

  1. Неправильная конфигурация (не выделяется достаточно памяти)
  2. Приложение непреднамеренно содержит ссылки на объекты, что предотвращает сборку мусора.
  3. Приложения, чрезмерно использующие финализаторы. Если у класса есть метод finalize, то пространство для объектов этого типа не освобождается во время сборки мусора. Если поток финализатора не может справиться с очередью финализации, то куча Java может заполниться, и возникнет исключение OutOfMemoryError этого типа .

С другой стороны, используйте лучшие алгоритмы сборки мусора ( CMS или G1GC ).

Взгляните на этот вопрос, чтобы понять G1GC


5
  1. В большинстве случаев код не оптимизирован. Освободите те предметы, которые, по вашему мнению, в дальнейшем не понадобятся. Избегайте создания объектов в вашем цикле каждый раз. Попробуйте использовать кеши. Я не знаю, как дела у вашего приложения. Но в программировании действует и одно правило нормальной жизни.

    Профилактика лучше, чем лечение. «Не создавайте лишних предметов»


3
  1. Локальные переменные находятся в стеке. Пространство кучи занято объектами.

  2. Вы можете использовать -Xmxопцию.

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


1

Нет, я думаю, вы думаете о пространстве стека. Пространство кучи занято объектами. Способ увеличения - -Xmx256m, заменив 256 на нужную вам сумму в командной строке.


1

Чтобы избежать этого исключения, если вы используете JUnit и Spring, попробуйте добавить это в каждый тестовый класс:

@DirtiesContext(classMode = DirtiesContext.ClassMode.AFTER_CLASS)

0

В netbeans перейдите на панель инструментов «Выполнить», -> «Установить конфигурацию проекта» -> «Настроить» -> «запустить» его всплывающего окна windo -> «Вариант виртуальной машины» -> заполните «-Xms2048m» -Xmx2048m '. Это может решить проблему размера кучи.

Используя наш сайт, вы подтверждаете, что прочитали и поняли нашу Политику в отношении файлов cookie и Политику конфиденциальности.
Licensed under cc by-sa 3.0 with attribution required.