Как вы находите утечку памяти в Java (используя, например, JHat)? Я попытался загрузить дамп кучи в JHat, чтобы получить базовый взгляд. Тем не менее, я не понимаю, как я могу найти корневую ссылку ( ref ) или как она там называется. По сути, я могу сказать, что существует несколько сотен мегабайт записей хеш-таблиц ([java.util.HashMap $ Entry или что-то в этом роде), но карты используются повсеместно ... Есть ли способ поиска больших карт или, может быть, найти общие корни деревьев больших объектов?
[Править] Хорошо, я до сих пор читал ответы, но давайте просто скажем, что я дешевый ублюдок (то есть меня больше интересует изучение того, как использовать JHat, чем платить за JProfiler). Кроме того, JHat всегда доступен, поскольку он является частью JDK. Если, конечно, с JHat нет другого пути, кроме грубой силы, но я не могу поверить в это.
Кроме того, я не думаю, что смогу реально изменить (добавив логирование всех размеров карт) и запустить его достаточно долго, чтобы я заметил утечку.
источник
Ответы:
Я использую следующий подход к поиску утечек памяти в Java. Я использовал jProfiler с большим успехом, но я считаю, что любой специализированный инструмент с графическими возможностями (различия легче анализировать в графической форме) будет работать.
По сути, анализ должен начинаться с наибольших положительных различий, скажем, по типам объектов и определять, что заставляет эти дополнительные объекты оставаться в памяти.
Для веб-приложений, обрабатывающих запросы в нескольких потоках, анализ становится более сложным, но, тем не менее, общий подход по-прежнему применяется.
Я выполнил целый ряд проектов, специально направленных на уменьшение объема памяти приложений, и этот общий подход с некоторыми специфическими настройками и трюками для приложений всегда работал хорошо.
источник
Спрашивающий здесь, я должен сказать, что получение инструмента, который не займет 5 минут, чтобы ответить на любой щелчок, значительно облегчает поиск потенциальных утечек памяти.
Поскольку люди предлагают несколько инструментов (я пробовал только Visual WM, так как я получил это в пробной версии JDK и JProbe), хотя я должен предложить бесплатный инструмент с открытым исходным кодом, построенный на платформе Eclipse, анализатор памяти (иногда упоминаемый как память SAP анализатор) доступно на http://www.eclipse.org/mat/ .
Что действительно круто в этом инструменте, так это то, что он впервые проиндексировал дамп кучи, когда я впервые открыл его, что позволило ему отображать данные, такие как сохраненная куча, без ожидания 5 минут для каждого объекта (почти все операции были на много быстрее, чем другие инструменты, которые я пробовал) ,
Когда вы открываете дамп, на первом экране отображается круговая диаграмма с самыми большими объектами (считая оставшуюся кучу), и вы можете быстро перейти к объектам, которые должны быть большими для удобства. У него также есть подозрения на наличие вероятных утечек, которые, по моему мнению, могут пригодиться, но поскольку навигации мне было достаточно, я не очень понял.
источник
HeapDumpOnCtrlBreak
параметр VM недоступен . Решение, которое я нашел (до сих пор продолжаю искать), состоит в том, чтобы использовать JMap для выгрузки.hprof
файла, который я затем помещаю в Eclipse и использую MAT для проверки.Инструмент - большая помощь.
Однако бывают случаи, когда вы не можете использовать инструмент: дамп кучи настолько велик, что он вылетает из строя, вы пытаетесь устранить неполадки компьютера в какой-либо производственной среде, к которой у вас есть доступ только к оболочке и т. Д.
В этом случае это поможет вам разобраться в файле дампа hprof.
Ищите САЙТ НАЧАТЬ. Это показывает, какие объекты используют больше всего памяти. Но объекты не объединяются только по типу: каждая запись также содержит идентификатор «trace». Затем вы можете найти этот «TRACE nnnn», чтобы увидеть несколько верхних фреймов стека, в котором был размещен объект. Часто, когда я вижу, где расположен объект, я нахожу ошибку и все готово. Также обратите внимание, что вы можете контролировать, сколько кадров записывается в стеке с помощью параметров -Xrunhprof.
Если вы просматриваете сайт размещения и не видите в этом ничего плохого, вы должны начать обратное сцепление некоторых из этих живых объектов с корневыми объектами, чтобы найти неожиданную цепочку ссылок. Здесь инструмент действительно помогает, но вы можете сделать то же самое вручную (ну, с помощью grep). Существует не только один корневой объект (т. Е. Объект, не подлежащий сборке мусора). Потоки, классы и стековые фреймы действуют как корневые объекты, и все, на что они сильно ссылаются, не подлежит коллекционированию.
Чтобы создать цепочку, посмотрите в разделе HEAP DUMP записи с ошибочным идентификатором трассировки. Это приведет вас к записи OBJ или ARR, которая показывает уникальный идентификатор объекта в шестнадцатеричном формате. Поиск всех вхождений этого идентификатора, чтобы найти, кто имеет сильную ссылку на объект. Следуйте каждому из этих путей в обратном направлении, пока они не разветвляются, пока не выясните, где находится утечка. Видишь, почему инструмент так удобен?
Статические члены являются повторным преступником для утечек памяти. На самом деле, даже без инструмента, стоило бы потратить несколько минут на просмотр вашего кода для статических членов Map. Может ли карта стать большой? Что-нибудь очищает его записи?
источник
jhat
и, по-MAT
видимому, пытался загрузить весь дамп кучи в память и, как правило, вылетал сOutOfMemoryError
большими дампами (т. Е. Из приложений, которые больше всего нуждались в анализе кучи! ). Профилировщик NetBeans, похоже, использует другой алгоритм для индексации ссылок, который может работать медленно на больших дампах, но, по крайней мере, не использует неограниченную память в инструменте и аварийно завершает работу.В большинстве случаев в корпоративных приложениях указанная куча Java больше идеального размера - от 12 до 16 ГБ. Мне было трудно заставить профилировщик NetBeans работать непосредственно с этими большими Java-приложениями.
Но обычно это не нужно. Вы можете использовать утилиту jmap, которая поставляется вместе с jdk, чтобы получить «живой» дамп кучи, то есть jmap выгрузит кучу после запуска GC. Сделайте некоторую операцию с приложением, дождитесь завершения операции, затем сделайте еще один «живой» дамп кучи. Используйте такие инструменты, как Eclipse MAT, чтобы загружать heapdumps, сортировать по гистограмме, видеть, какие объекты увеличились или какие являются самыми высокими. Это даст подсказку.
Есть только одна проблема с этим подходом; Огромные дампы кучи, даже с опцией live, могут быть слишком большими для переноса на этап разработки, и для их открытия может потребоваться машина с достаточным объемом памяти / ОЗУ.
Вот где гистограмма класса входит в картину. Вы можете вывести гистограмму живого класса с помощью инструмента jmap. Это даст только гистограмму класса использования памяти. В основном у нее не будет информации, чтобы связать ссылку. Например, он может поместить массив символов сверху. И класс String где-то внизу. Вы должны нарисовать связь самостоятельно.
Вместо двух дампов кучи возьмите две гистограммы классов, как описано выше; Затем сравните гистограммы классов и посмотрите, какие классы увеличиваются. Посмотрите, можете ли вы связать классы Java с классами вашего приложения. Это даст довольно хороший намек. Вот скрипт pythons, который может помочь вам сравнить два дампов гистограммы jmap. histogramparser.py
Наконец, такие инструменты, как JConolse и VisualVm, необходимы для наблюдения за увеличением объема памяти и выявления утечки памяти. Наконец, иногда ваша проблема может заключаться не в утечке памяти, а в ее большом использовании памяти. Для этого включите ведение журнала GC, используйте более продвинутый и новый GC сжатия, такой как G1GC; и вы можете использовать инструменты JDK, такие как Jstat, чтобы увидеть поведение GC в прямом эфире
Другие ссылки на Google для -jhat, Jmap, Full GC, Humongous распределения, G1GC
источник
Существуют инструменты, которые должны помочь вам найти утечку, такие как JProbe, YourKit, AD4J или JRockit Mission Control. Последнее, что я лично знаю лучше всего. Любой хороший инструмент должен позволить вам перейти к уровню, на котором вы можете легко определить, какие утечки и где распределяются объекты утечки.
Использование HashTables, Hashmaps или аналогичных является одним из немногих способов, которыми вы можете вообще утечь память в Java. Если бы мне пришлось искать утечку вручную, я бы перидически печатал размер моих HashMaps, а оттуда находил тот, где я добавлял элементы, и забывал их удалять.
источник
Что ж, всегда есть низкотехнологичное решение: добавить журнал размера ваших карт, когда вы их изменяете, а затем искать в журналах, карты которых растут за пределами разумного размера.
источник
NetBeans имеет встроенный профилировщик.
источник
Вам действительно нужно использовать профилировщик памяти, который отслеживает распределение. Взгляните на JProfiler - их отличная функция «обхода кучи» и их интеграция со всеми основными Java IDE. Это не бесплатно, но и не так дорого (499 долл. За одну лицензию) - вы потратите на 500 долл. Времени довольно быстро, пытаясь найти утечку с помощью менее сложных инструментов.
источник
Это можно узнать, измерив объем использования памяти после многократного вызова сборщика мусора:
Если выходные значения были равны, то в вашем приложении нет утечки памяти, но если вы увидели разницу между числами использования памяти (увеличивающиеся числа), в вашем проекте есть утечка памяти. Например:
Обратите внимание, что иногда для освобождения памяти требуются некоторые действия, такие как потоки и сокеты. Вы не должны судить по первым результатам, вы должны проверить это в течение определенного времени.
источник
Оформить заказ этот скриншот о поиске утечек памяти с JProfiler. Это визуальное объяснение @Dima Malenko Ответ.
Примечание: хотя JProfiler не является бесплатной, но пробная версия может справиться с текущей ситуацией.
источник
Поскольку большинство из нас уже используют Eclipse для написания кода, почему бы не использовать инструмент анализатора памяти (MAT) в Eclipse. Работает отлично.
Затмение MAT представляет собой набор плагинов для IDE Eclipse , который предоставляет инструменты для анализа
heap dumps
из приложения Java и определитьmemory problems
в приложении.Это помогает разработчику обнаруживать утечки памяти с помощью следующих функций
источник