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

Мой код делает такие вещи:

for(SomeObject so : someObjects)
{
  Blah b = so;
  NewObject n = dao.GetNO(b.23);
}

т.е. он создает новую переменную внутри цикла for на каждой итерации.

Может ли это быть причиной нехватки памяти?

Ошибка, о которой сообщает Netbeans:

Caused by: java.lang.OutOfMemoryError: Java heap space
        at java.lang.StringCoding$StringDecoder.decode(StringCoding.java:133)
        at java.lang.StringCoding.decode(StringCoding.java:173)
        at java.lang.String.<init>(String.java:443)
        at java.lang.String.<init>(String.java:515)
        at com.gargoylesoftware.htmlunit.WebResponseImpl.getContentAsString(WebResponseImpl.java:215)
        at com.gargoylesoftware.htmlunit.WebResponseImpl.getContentAsString(WebResponseImpl.java:205)

Upate. Это консольное приложение Java, и все приложение в основном запускает цикл forloop.


person mrblah    schedule 06.01.2010    source источник
comment
Это МОЖЕТ быть причиной, но не обязательно. Постарайтесь освободить каждый предмет, который вам больше не нужен. В частности, проверьте все свои коллекции (карты, списки, ...), если вы храните там объекты, которые больше не нужны.   -  person Peter Schuetze    schedule 06.01.2010
comment
Какой у вас размер кучи?   -  person Taylor Leese    schedule 06.01.2010
comment
Можете ли вы опубликовать еще немного фактического кода, в котором возникает ошибка? Одно замечание: возвращаемое значение com.gargoylesoftware.htmlunit.WebResponseImpl.getContentAsString(), вероятно, будет довольно большой строкой.   -  person MatrixFrog    schedule 06.01.2010
comment
matrixfrog, это очень большая строка, весь HTML-код страницы размером около 120 КБ.   -  person mrblah    schedule 06.01.2010


Ответы (3)


Вы используете Java 5 или выше или одну из устаревших JVM? Вы можете попытаться отследить причину своего OOM, активировав свою командную строку Java с помощью -XX: + HeapDumpOnOutOfMemory или подключившись к своему процессу с помощью JConsole и запросить дамп кучи. Затем вы можете использовать инструмент Eclipse MAT, чтобы открыть дамп и просмотреть граф объекта, чтобы узнать, чья на объекты в вашей программе. MAT имеет представление, чтобы увидеть те объекты, которые доминируют в графе объектов, поэтому становится предельно ясно, что именно происходит. Просмотр трассировки стека бесполезен и может вводить в заблуждение, потому что утечка в одном месте программы может привести к неудачному распределению в другом месте.

person Amir Afghani    schedule 06.01.2010
comment
Это кажется излишним, учитывая масштаб описанной проблемы. - person Steve B.; 07.01.2010
comment
Действительно? Знание, какие объекты занимают кучу после того, как я увижу OOM, для меня не излишне. - person Amir Afghani; 07.01.2010

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

Итак, если вы напишете

for (.....){
   Object o = new Object();
}

-вы никогда не храните более одного экземпляра o, поэтому он не будет причиной (если вы не сохраняете ссылку на них где-то еще, например, помещая их на карту за пределами области цикла).

Вам нужно найти место в коде, где будет больше ссылок. Из вашей публикации невозможно сказать больше.

Кстати, вы также можете подумать об увеличении объема памяти, который вы используете в своей JVM, с помощью параметров -Xmx и -Xms (введите «java -X» для получения дополнительной информации), что может заставить его работать, хотя он не помогите найти ошибку. Поскольку вы работаете внутри netbeans, вам также может не хватить памяти, потому что он работает в той же JVM. Я не использую netbeans, но вы можете проверить и посмотреть, позволяет ли netbeans разветвлять новый процесс для запуска вашей программы (чтобы вы не пытались запустить при совместном использовании памяти с netbeans, что не мало), или попробовать работает прямо в командной строке.

person Steve B.    schedule 06.01.2010

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

Другая возможность состоит в том, что вам просто не хватает памяти для того, что вы делаете. Java запускается (по крайней мере, Sun по умолчанию) с 64 МБ кучи. Вы можете изменить это с помощью параметра -xmx.

Наконец, я вспоминаю, что в 1.4.X days вы могли вызвать OutOfMemoryError, если бы достаточно времени (в процентах от общего времени ЦП процесса) было потрачено на сборку мусора (для какой-то конкретной реализации сборщика мусора). Отсечка находилась в диапазоне 90%. Я видел это раз в почти десять лет, и это был действительно невротический вариант использования. Возможно, дело не в этом, но может быть. Я не уверен, что такое поведение сохраняется в современной Java.

Мой совет: проверьте реализацию dao.GetNO(...) и посмотрите, создает ли он какие-либо объекты в качестве побочного эффекта и каковы их сроки жизни.

person Kevin Montrose    schedule 06.01.2010