Это почти невозможно без некоторого понимания базового кода. Если вы понимаете базовый код, тогда вы можете лучше сортировать пшеницу из мякины из миллионных бит информации, которую вы получаете в своих кучих свалок.
Кроме того, вы не можете знать, есть ли что-то утечка или нет, не зная, почему класс в первую очередь.
Я только что провел пару недель, выполняя именно это, и я использовал итеративный процесс.
Во-первых, я обнаружил, что профилирующие кучи в основном бесполезны. Они не могут эффективно анализировать огромные кучи.
Скорее, я полагался почти исключительно на гистограммы jmap.
Я полагаю, что вы знакомы с этим, но для тех, кто не:
jmap -histo:live <pid> > dump.out
создает гистограмму живой кучи. В двух словах он сообщает вам имена классов и количество экземпляров каждого класса в куче.
Я регулярно выгружаю кучу, каждые 5 минут, 24 часа в сутки. Это может быть слишком сложным для вас, но суть одна и та же.
Я провел несколько различных анализов по этим данным.
Я написал сценарий, чтобы взять две гистограммы и сбросить разницу между ними. Итак, если java.lang.String было 10 в первой дампе, а 15 во втором, мой скрипт выплюнул бы «5 java.lang.String», сказав мне, что он поднялся на 5. Если он упал, число будет отрицательным.
Я бы воспользовался несколькими из этих различий, разделив все классы, которые спустились с бега на бег, и объедините результат. В конце концов, у меня будет список классов, которые постоянно росли в течение определенного периода времени. Очевидно, что это основные кандидаты на утечку классов.
Однако некоторые классы сохранены, а другие - GC'd. Эти классы могли легко подниматься и опускаться в целом, но все же течь. Таким образом, они могут выпадать из категории «всегда поднимающихся» классов.
Чтобы найти их, я преобразовал данные в временные ряды и загрузил их в базу данных, Postgres специально. Postgres удобен, потому что он предлагает statistical aggregate functions, поэтому вы можете сделать простые данные linear regression analysis и найти классы, которые растут, даже если они не всегда находятся на вершине диаграмм. Я использовал функцию regr_slope, ища классы с положительным наклоном.
Я нашел этот процесс очень успешным и действительно эффективным. Файлы гистограмм не безумно большие, и их было легко загрузить с хостов. Они не были слишком дороги для запуска в производственной системе (они заставляют большой GC и могут немного заблокировать виртуальную машину). Я запускал это в системе с кучей 2G Java.
Теперь все это может означать потенциально протекающие классы.
Здесь понимают, как используются классы, и должны ли они быть или не быть их участниками, чтобы играть.
Например, вы можете обнаружить, что у вас много классов Map.Entry или какой-либо другой системный класс.
Если вы просто не кешируете String, факт состоит в том, что эти системные классы, хотя, возможно, и «нарушители», не являются «проблемой». Если вы кэшируете некоторый класс приложения, класс THAT является лучшим индикатором того, где ваша проблема. Если вы не кэшируете com.app.yourbean, то у вас не будет привязана связанная с ним Map.Entry.
Как только у вас есть несколько классов, вы можете начать сканирование базы кода в поисках экземпляров и ссылок. Поскольку у вас есть собственный уровень ORM (для хорошего или плохого), вы можете, по крайней мере, с готовностью посмотреть на исходный код. Если вы ORM - это кеширование, вероятно, кеширование классов ORM завершает ваши классы приложений.
Наконец, еще одна вещь, которую вы можете сделать, - это то, что вы знаете классы, вы можете запустить локальный экземпляр сервера с гораздо меньшей кучей и меньшим набором данных и использовать один из профилировщиков против этого.
В этом случае вы можете выполнить единичный тест, который затрагивает только 1 (или небольшое количество) тех вещей, которые, по вашему мнению, могут протекать. Например, вы можете запустить сервер, запустить гистограмму, выполнить одно действие и снова запустить гистограмму. Класс утечки должен увеличиться на 1 (или независимо от вашей единицы работы).
Профилировщик может помочь вам отследить владельцев этого «просочившегося» класса.
Но, в конце концов, вам нужно будет иметь некоторое представление о вашей базе кода, чтобы лучше понять, что такое утечка, а что нет, и почему объект существует в куче вообще, а тем более почему это может сохраняться как утечка в вашей куче.
Я купил больше памяти – LB40
@LB У нас есть 64 ГБ, но бюджет для этого приложения составляет всего 2 ГБ, и мы не можем разумно увеличить больше пары ГБ, не начав каннибализировать другие подсистемы. –
Кучи кучи специфичны для JVM, поэтому вам нужно использовать инструмент, соответствующий JVM. Это? –