java - утечка - permgen что это




Как найти утечку памяти Java (6)

Как вы обнаружите утечку памяти в Java (используя, например, JHat)? Я попытался загрузить кучу кучи в JHat, чтобы получить базовый вид. Тем не менее, я не понимаю, как я должен найти корневую ссылку ( ref ) или что бы то ни было. В принципе, я могу сказать, что есть несколько сотен мегабайт записей хеш-таблицы ([java.util.HashMap $ Entry или что-то в этом роде), но карты используются повсюду ... Есть ли способ поиска больших карт , или, возможно, найти общие корни больших деревьев объектов?

[Изменить] Хорошо, я прочитал ответы до сих пор, но давайте просто скажем, что я дешевый ублюдок (это значит, что меня больше интересует, как использовать JHat, чем платить за JProfiler). Кроме того, JHat всегда доступен, поскольку он является частью JDK. Если, конечно, нет никакого отношения к JHat, кроме грубой силы, но я не могу поверить, что это может быть так.

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


NetBeans имеет встроенный профилировщик.


Большую часть времени в корпоративных приложениях куча Java больше, чем идеальный размер от 12 до 16 ГБ. Мне было трудно заставить профилировщик NetBeans работать непосредственно над этими большими приложениями Java.

Но обычно это не нужно. Вы можете использовать утилиту jmap, которая поставляется вместе с jdk, чтобы взять «живой» кучи кучи, то есть jmap выгрузит кучу после запуска GC. Сделайте некоторую операцию над приложением, дождитесь завершения операции, затем возьмите другую «живую» кучу кучи. Используйте такие инструменты, как Eclipse MAT, чтобы загружать кучи, сортировать по гистограмме, видеть, какие объекты увеличились или которые являются самыми высокими. Это даст ключ.

su  proceeuser
/bin/jmap -dump:live,format=b,file=/tmp/2930javaheap.hrpof 2930(pid of process)

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

Вот где картинка класса входит в картину. Вы можете сбросить гистограмму живого класса с помощью инструмента jmap. Это даст только гистограмму класса памяти. В основном у нее не будет информации для привязки ссылки. Например, он может помещать массив символов вверху. И класс String где-то ниже. Вы должны сами подключить соединение.

jdk/jdk1.6.0_38/bin/jmap -histo:live 60030 > /tmp/60030istolive1330.txt

Вместо того, чтобы брать две свалки кучи, возьмите две гистограммы классов, как описано выше; Затем сравните гистограммы классов и посмотрите классы, которые увеличиваются. Посмотрите, можете ли вы связать классы Java с вашими классами приложений. Это даст довольно хороший намек. Вот сценарий pythons, который может помочь вам сравнить два дампа гистограммы jmap. histogramparser.py

Наконец, такие инструменты, как JConolse и VisualVm, необходимы для того, чтобы увидеть рост памяти с течением времени и посмотреть, есть ли утечка памяти. Наконец, иногда ваша проблема может быть не утечкой памяти, а высокой потребляемой памятью. Для этого включите GC-протоколирование, используйте более совершенный и новый уплотняющий GC, такой как G1GC; и вы можете использовать инструменты jdk, такие как jstat, чтобы увидеть поведение GC в реальном времени

jstat -gccause pid <optional time interval>

Другие референции для google для -jhat, jmap, Full GC, Humongous distribution, G1GC


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

Поскольку люди предлагают несколько инструментов (я только пробовал визуальный wm, так как получил это в пробной версии JDK и JProbe), я должен предложить бесплатный инструмент с открытым исходным кодом, построенный на платформе Eclipse, анализатор памяти (иногда называемый памятью SAP анализатор), доступный на http://www.eclipse.org/mat/ .

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

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


Инструмент - большая помощь.

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

В этом случае он помогает узнать свой путь по файлу дампа hprof.

Ищите НАЧАЛО САЙТОВ. Это показывает, какие объекты используют большую часть памяти. Но объекты не собираются вместе только по типу: каждая запись также содержит идентификатор «trace». Затем вы можете найти этот «TRACE nnnn», чтобы увидеть несколько лучших кадров стека, где был выделен объект. Часто, когда я вижу, где объект выделен, я нахожу ошибку, и все готово. Также обратите внимание, что вы можете контролировать, сколько кадров записано в стеке с параметрами -Xrunhprof.

Если вы проверите сайт распределения и не увидите ничего плохого, вам нужно начать обратную привязку от некоторых из этих живых объектов к корневым объектам, чтобы найти неожиданную цепочку ссылок. Здесь инструмент действительно помогает, но вы можете сделать то же самое вручную (ну, с grep). Существует не только один объект root (т. Е. Объект, не подлежащий сборке мусора). Нити, классы и фреймы стека действуют как корневые объекты, и все, что они ссылаются строго, не является коллекционируемым.

Чтобы выполнить цепочку, просмотрите раздел HEAP DUMP для записей с плохим идентификатором трассировки. Это приведет к записи OBJ или ARR, которая показывает уникальный идентификатор объекта в шестнадцатеричном формате. Найдите все вхождения этого идентификатора, чтобы найти, кто имеет сильную ссылку на объект. Следуйте по каждому из этих путей назад, когда они разветвятся, пока не выясните, где находится утечка. Посмотрите, почему инструмент настолько удобен?

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


Существуют инструменты, которые помогут вам найти утечку, например, JProbe, YourKit, AD4J или JRockit Mission Control. Последнее самое, что я лично знаю лучше всего. Любой хороший инструмент должен позволить вам развернуться до уровня, где вы можете легко определить, какие утечки и где выделяются объекты утечки.

Использование HashTables, Hashmaps или аналогичного является одним из немногих способов, которыми вы можете полностью протекать в памяти на Java. Если бы я должен был найти утечку вручную, я бы опечатал размер моих HashMaps, и оттуда найду ту, где я добавляю элементы и забываю их удалить.


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

  1. Запустите приложение и подождите, пока он не достигнет «стабильного» состояния, когда вся инициализация завершена и приложение не работает.
  2. Запустите операцию, предположительно, чтобы произвести утечку памяти несколько раз, чтобы разрешить любую кеш, связанную с DB инициализацию.
  3. Запустите GC и сделайте снимок памяти.
  4. Повторите операцию. В зависимости от сложности работы и размеров данных, которые обрабатываются, может потребоваться несколько раз.
  5. Запустите GC и сделайте снимок памяти.
  6. Запустите diff для двух снимков и проанализируйте его.

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

Для веб-приложений, обрабатывающих запросы в нескольких потоках, анализ становится более сложным, но тем не менее общий подход все же применяется.

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





jhat