Вопрос

Как лучше всего отлаживать java.lang.OutOfMemoryError Исключения?

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


ОБНОВЛЕНИЕ: Как лучше всего сгенерировать дампы потоков? Является kill -3 (Наше приложение работает на Solaris) Лучший способ убить приложение и генерировать дамп потока? Есть ли способ генерировать дамп потока, но не убить приложение?

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

Решение

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

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

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

Запустите свой процесс -XX:+HeapDumpOnOutOfMemoryError -XX:HeapDumpPath=/tmp

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

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

Пусть приложение запустится до OutOfMemoryError имеет место.

JVM автоматически напишет файл подобным java_pid12345.hprof.

Шаг 3. Принесите свалку

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

Шаг 4. Откройте файл дампа с помощью IBM Анализатор кучи или затмение Анализатор памяти

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

IBM HeapAnalyzer

Примечание. Дайте Heapanalyzer достаточно памяти, так как он должен загрузить весь ваш дамп!

java -Xmx10g -jar ha456.jar

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

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

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

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

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

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

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

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

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

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

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

Вы также можете использовать 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/technicalarticlics/j2se/monitoring/

Как лучше всего отлаживать java.lang.OutOfMemoryError Исключения?

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

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

java.lang.OutOfMemoryError: Java heap space:

Причина: Подробное сообщение Java Heap Space указывает, что объект не может быть выделен в куче 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 Class (внутреннее представление класса Java Virtual Machines) выделено в нативной памяти (упоминается здесь как Metaspace)

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

Причина: Подробное сообщение «РАЗМЕР ЗАПРОСЫ БАЙТЫ по разуму. Вне пространства свопа?» кажется OutOfMemoryError исключение. Тем не менее, код VM Java Hotspot сообщает об этом явном исключении, когда выдел от нативного кучи не удалось и нативная куча может быть близка к истощению

java.lang.OutOfMemoryError: Compressed class space

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

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

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

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

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

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

Разница между Javacore, Thread Dilm и Heap Damp в WebSphere

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

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

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

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

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

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

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

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

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