это - Метод обнаружения утечки памяти в больших кучах кучи Java




утечка памяти java это (5)

Взгляните на Eclipse Memory Analyzer . Это отличный инструмент (и автономный, не требует самого Eclipse), который 1) может очень быстро открывать очень большие кучи и 2) имеет некоторые довольно хорошие инструменты автоматического обнаружения. Последнее не идеально, но EMA предоставляет множество действительно хороших способов навигации и запросов объектов на дампе, чтобы найти возможные утечки.

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

https://code.i-harness.com

Я должен найти утечку памяти в приложении Java. У меня есть некоторый опыт в этом, но я бы хотел получить совет по методологии / стратегии для этого. Любые рекомендации и рекомендации приветствуются.

О нашей ситуации:

  1. Кучи кучи больше 1 ГБ
  2. У нас есть отвалы кучи от 5 случаев.
  3. У нас нет тестового примера, чтобы спровоцировать это. Это происходит только в (массивной) тестовой среде системы после использования по крайней мере в течение недели.
  4. Система построена на внутренней структуре устаревших систем с таким количеством недостатков дизайна, что их невозможно сосчитать.
  5. Никто не понимает структуру в глубину. Он был передан одному парню в Индии, который едва успевает отвечать на электронные письма.
  6. С течением времени мы сделали отвалы кучи снимков, и пришли к выводу, что со временем не наблюдается ни одного компонента. Это все, что растет медленно.
  7. Вышеупомянутое указывает на то, что он является основой доморощенной системы ORM, которая увеличивает ее использование без ограничений. (Эта система сопоставляет объекты с файлами ?! Значит, это не ORM)

Вопрос: Какова методология, которая помогла вам добиться успеха при поиске утечек в приложении масштаба предприятия?


Если это происходит после использования в течение недели, и ваше приложение является как byzantine, как вы описываете, возможно, вам лучше перезапустить его каждую неделю?

Я знаю, что это не проблема, но это может быть временное решение. Есть ли окна времени, когда вы можете отключиться? Можете ли вы загрузить баланс и провалиться за один экземпляр, сохранив второй? Возможно, вы можете инициировать перезапуск, когда потребление памяти нарушает определенный предел (возможно, мониторинг через JMX или аналогичный).


У меня был успех с IBM Heap Analyzer . Он предлагает несколько представлений о куче, включая наибольшее падение размера объекта, наиболее часто встречающихся объектов и объектов, отсортированных по размеру.


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

Кроме того, вы не можете знать, есть ли что-то утечка или нет, не зная, почему класс в первую очередь.

Я просто провел последние пару недель, выполняя именно это, и я использовал итеративный процесс.

Во-первых, я обнаружил, что профилирующие кучи в основном бесполезны. Они не могут эффективно анализировать огромные кучи.

Скорее, я полагался почти исключительно на гистограммы jmap .

Я думаю, вы знакомы с ними, но для тех,

jmap -histo:live <pid> > dump.out

создает гистограмму живой кучи. В двух словах он сообщает вам имена классов и количество экземпляров каждого класса в куче.

Я регулярно выворачивал кучу, каждые 5 минут, 24 часа в день. Это может быть слишком сложным для вас, но суть одна и та же.

Я провел несколько различных анализов по этим данным.

Я написал сценарий, чтобы взять две гистограммы и сбросить разницу между ними. Итак, если java.lang.String было 10 в первой дампе, а 15 во втором, мой скрипт выплюнул бы «5 java.lang.String», сказав мне, что он поднялся на 5. Если он упал, число будет отрицательным.

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

Однако некоторые классы сохранены, а другие - GC'd. Эти классы могли легко подниматься и опускаться в целом, но все же течь. Таким образом, они могут выпадать из категории «всегда поднимающихся» классов.

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

Я нашел этот процесс очень успешным и действительно эффективным. Файлы гистограмм не безумно большие, и их было легко загрузить с хостов. Они не были слишком дороги для запуска в производственной системе (они заставляют большой GC и могут немного заблокировать виртуальную машину). Я запускал это в системе с кучей 2G Java.

Теперь все это может означать потенциально протекающие классы.

Здесь понимают, как используются классы, и должны ли они или не должны быть их участниками, чтобы играть.

Например, вы можете обнаружить, что у вас много классов Map.Entry или какой-либо другой системный класс.

Если вы просто не кешируете String, факт - это эти системные классы, а, возможно, «нарушители», не являются «проблемой». Если вы кэшируете некоторый класс приложения, класс THAT является лучшим индикатором того, где ваша проблема. Если вы не кэшируете com.app.yourbean, то у вас не будет привязана связанная с ним Map.Entry.

После того, как у вас есть несколько классов, вы можете начать сканирование базы кода, ищущей экземпляры и ссылки. Поскольку у вас есть собственный уровень ORM (для хорошего или плохого), вы можете, по крайней мере, с готовностью посмотреть на исходный код. Если вы ORM - это кеширование, вероятно, кеширование классов ORM завершает ваши классы приложений.

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

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

Профилировщик может помочь вам отслеживать владельцев этого «просочившегося» класса.

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


Я использовал jhat , это немного jhat , но это зависит от того, какие у вас были рамки.







memory-leaks