Как отладить исключения Java OutOfMemory? - PullRequest
12 голосов
/ 22 декабря 2010

Каков наилучший способ отладки java.lang.OutOfMemoryError исключений?

Когда это происходит с нашим приложением, наш сервер приложений (Weblogic) генерирует файл дампа кучи. Должны ли мы использовать файл дампа кучи? Должны ли мы генерировать дамп потока Java? В чем именно разница?


Обновление: каков наилучший способ создания дампов потоков? kill -3 (наше приложение работает на Solaris) - лучший способ убить приложение и создать дамп потока? Есть ли способ создать дамп потока, но не убить приложение?

Ответы [ 8 ]

6 голосов
/ 22 декабря 2010

Я успешно использовал комбинацию Eclipse Memory Analyzer (MAT) и Java Visual VM для анализа дампов кучи.У MAT есть несколько отчетов, которые вы можете запускать, которые дают вам общее представление о том, где сосредоточить свои усилия в своем коде.VisualVM имеет лучший интерфейс (на мой взгляд) для проверки содержимого различных объектов, которые вы хотите исследовать.У него есть фильтр, в котором вы можете отобразить все экземпляры определенного класса и увидеть, где на них ссылаются и на что они ссылаются.Прошло много времени с тех пор, как я использовал любой инструмент для этого, у них теперь может быть более близкий набор функций.В то время использование обоих работало хорошо для меня.

3 голосов
/ 19 мая 2016

Каков наилучший способ отладки java.lang.OutOfMemoryError исключений?

OutOfMemoryError описывает тип ошибки в описании сообщения. Вы должны проверить описание сообщения об ошибке, чтобы обработать исключение.

Существуют различные первопричины исключений нехватки памяти. Обратитесь к документации оракула стр. для получения более подробной информации.

java.lang.OutOfMemoryError: Java heap space:

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

java.lang.OutOfMemoryError: GC Overhead limit exceeded

Причина: Подробное сообщение «Превышен лимит накладных расходов GC» указывает на то, что сборщик мусора работает все время, а Java-программа работает очень медленно

java.lang.OutOfMemoryError: Requested array size exceeds VM limit

Причина : подробное сообщение «Запрошенный размер массива превышает ограничение виртуальной машины» указывает, что приложение (или API, используемые этим приложением) пыталось выделить массив, размер которого больше размера кучи.

java.lang.OutOfMemoryError: Metaspace

Причина: Метаданные класса Java (внутреннее представление класса Java для виртуальных машин) размещаются в собственной памяти (называемой здесь метапространством)

java.lang.OutOfMemoryError: request size bytes for reason. Out of swap space?

Причина: Подробное сообщение "запросить размер байта по причине. Недостаточно места подкачки?" представляется исключением OutOfMemoryError. Однако код виртуальной машины Java HotSpot сообщает об этом явном исключении, когда выделение из собственной кучи завершилось неудачно, а собственная куча может быть близка к исчерпанию

java.lang.OutOfMemoryError: Compressed class space

Причина: На 64-битных платформах указатель на метаданные класса может быть представлен 32-битным смещением (с UseCompressedOops). Это контролируется флагом командной строки UseCompressedClassPointers (по умолчанию включен).

Если используется UseCompressedClassPointers, объем пространства, доступного для метаданных класса, устанавливается равным CompressedClassSpaceSize. Если пространство, необходимое для UseCompressedClassPointers, превышает CompressedClassSpaceSize, java.lang.OutOfMemoryError с подробностями Сжатое пространство класса выбрасывается.

Примечание: Существует несколько видов метаданных класса - метаданные класса и другие метаданные. Только метаданные класса хранятся в пространстве, ограниченном CompressedClassSpaceSize. Другие метаданные хранятся в Metaspace.

Должны ли мы использовать файл дампа кучи? Должны ли мы генерировать дамп потока Java? В чем именно разница?

Да. Вы можете использовать этот файл дампа кучи для устранения проблемы с помощью инструментов профилирования, таких как visualvm или mat Вы можете использовать дамп потока, чтобы получить дополнительную информацию о состоянии потоков.

Обратитесь к этому вопросу SE, чтобы узнать разницу:

Разница между javacore, дампом потока и дампом кучи в Websphere

Каков наилучший способ создания дампов потоков? Является ли kill -3 (наше приложение работает на Solaris) лучшим способом убить приложение и создать дамп потока? Есть ли способ создать дамп потока, но не убить приложение?

kill -3 <process_id> создает дамп потока, и эта команда не завершает процесс Java.

3 голосов
/ 22 декабря 2010

Вы также можете использовать jmap / jhat для подключения к работающему процессу Java.Эти (семейные) инструменты действительно полезны, если вам нужно отлаживать работающее приложение.

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

jmap -histo:live <pid> | head -n <top N things to look for> > <output.log>

Jmap также можно использовать для генерации дампа кучи с помощью опции -dump, которую можно прочитать через jhat.

Для получения дополнительной информации см. Следующую ссылку http://www.lshift.net/blog/2006/03/08/java-memory-profiling-with-jmap-and-jhat

Вот еще одна ссылка назакладка http://java.sun.com/developer/technicalArticles/J2SE/monitoring/

3 голосов
/ 22 декабря 2010

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

Чтобы ответить на ваши конкретные вопросы:

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

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

2 голосов
/ 11 января 2019

Анализировать и исправлять ошибки нехватки памяти в Java очень просто.

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

Шаг 1. Включите дампы кучи во время выполнения

Запустите ваш процесс с помощью -XX:+HeapDumpOnOutOfMemoryError -XX:HeapDumpPath=/tmp

(Эти параметры всегда безопасныПри необходимости измените путь, он должен быть доступен для записи пользователю java.

Шаг 2. Воспроизведите ошибку

Дайте приложению работать, пока не произойдет OutOfMemoryError.

JVM автоматически запишет файл типа java_pid12345.hprof.

Шаг 3. Извлеките дамп

Скопируйте java_pid12345.hprof на ваш компьютер (он будет по крайней мере настолько же большим, насколько ваша максимальная кучаразмер, так что может стать довольно большим - gzip его при необходимости).

Шаг 4. Откройте файл дампа с помощью IBM Heap Analyzer или Eclipse Memory Analyzer

Анализатор кучи подарит вам дерево всех предметовтс, которые были живы на момент ошибки.Скорее всего, он укажет непосредственно на проблему при ее открытии.

IBM HeapAnalyzer

Примечание: предоставьте HeapAnalyzer достаточно памяти, так какнеобходимо загрузить весь дамп!

java -Xmx10g -jar ha456.jar

Шаг 5. Определите области наибольшего использования кучи

Просмотрите дерево объектов и определите объекты, которые хранятся без необходимости.

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

Шаг 6. Исправьте код

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

2 голосов
/ 22 декабря 2010

Похоже, IBM предоставляет инструмент для анализа этих дампов кучи: http://www.alphaworks.ibm.com/tech/heaproots; больше на http://www -01.ibm.com / support / docview.wss? uid = swg21190476 .

1 голос
/ 05 мая 2015

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

Однако OOM не всегда означает, что произошла утечка памяти. Всегда возможно, что память, необходимая приложению в стабильном состоянии или под нагрузкой, недоступна в оборудовании / виртуальной машине. Например, это может быть 32-битный процесс Java (макс. Используемая память ~ 4 ГБ), где у виртуальной машины всего 3 ГБ. В таком случае изначально приложение может работать нормально, но с OOM можно столкнуться, когда и требования к памяти приближаются к 3 ГБ.

Как уже упоминалось другими, захват дампа потока не дорог, но захват дампа кучи - это. Я заметил, что во время захвата приложения дампа кучи (как правило) зависает, и только восстановление с последующим перезапуском помогает восстановить.

1 голос
/ 22 декабря 2010

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

Это должно указать вам правильное направление.Затем используйте стандартные методы отладки (ведение журнала, отладчик и т. Д.), Чтобы решить проблему.Используйте класс Runtime, чтобы получить текущее использование памяти и зарегистрировать его как выполняемый метод или рассматриваемый процесс.

...