Статьи

Plumbr 3.0 — эволюционный подход к утечкам памяти в Java


Большинство разработчиков Java знакомы с понятием «утечки памяти». В мире Java это по существу означает постоянное расширение определенного пространства памяти, такого как 
куча Java
PermGen  & 
Metaspace (Java 8)  или собственная память. Такие утечки часто являются результатом проблем с кодом Java из ваших приложений, API сторонней части или даже внутри контейнера Java EE и базы кода JDK. Уровень сложности, позволяющий точно определить и решить проблемы такого типа, может варьироваться от среднего до очень высокого.


Хорошей новостью является то, что JVM превратилась в великий инженерный проект. Алгоритмы GC, устранение неполадок и возможности обработки данных JVM в настоящее время достаточно развиты. У нас есть доступ к наиболее важным данным времени выполнения через JMX API. Все поставщики JVM также предоставляют
 методы генерации
дампов  и 
дампов JVM 
. Наконец, у нас также есть доступ к большому арсеналу инструментов и профилировщиков Java для мониторинга внутренних компонентов JVM и анализа дампов памяти, таких как JVisualVM, 
Eclipse MAT  или других коммерческих продуктов.


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


Недавно у меня была возможность поэкспериментировать с последней версией инструмента анализа утечек памяти Java, о котором вы наверняка слышали: 
Plumbr . Подход Plumbr может быть возобновлен следующим образом: вместо анализа дампов памяти «по факту» или следования
 условию
OutOfMemoryError , почему бы не написать программу, которая следит за объектами Java и точно обнаруживает подозреваемые утечки памяти во время выполнения… и с живым производством трафик?


Эта статья поделится положительным опытом, который я получил с этим продуктом, когда экспериментировал и «проектировал» утечку памяти кучи Java с помощью последней версии 
WildFly  (ранее известной как JBoss AS). Я также поделюсь своими личными советами о том, как улучшить ваш опыт устранения неполадок с Plumbr путем объединения дополнительных инструментов или «синергистов». Полное учебное видео Plumbr также будет доступно на моем 
канале YouTube  в ближайшем будущем.


Plumbr также имеет возможность определять утечки памяти, связанные с загрузчиком классов, которые влияют на пространство PermGen JVM HotSpot.
Я могу опубликовать больше статей в будущем, посвященных этой конкретной утечке, с помощью Plumbr.

Симулятор утечки памяти и характеристики среды


Для решения проблем Plumbr была разработана следующая утечка памяти:
  • Веб-служба JAX-RS (REST) ​​была создана и предоставлена ​​через URI jvmleak согласно приведенным ниже атрибутам.
@GET
@Path("/jvmleak")
@Produces(MediaType.APPLICATION_JSON)
public Integer jvmLeak() {}

Каждый вызов jvmleak выполняет следующую логику:

1. Выделите большое количество недолговечных объектов (без ссылки).


2. Выделите небольшое количество долгоживущих объектов (нормальные или жесткие ссылки) в статическую структуру данных ConcurrentHashMap.


3. Возвращает текущий счетчик «текущей» ConcurrentHashMap.


Мы также создали 3 дополнительных класса Java:
  • JVMMemoryAllocator. Этот класс отвечает за распределение недолгой и долгоживущей памяти.
  • ShortLivedObj. Этот класс представляет недолговечный объект без ссылки.
  • LongLivedObj. Этот класс представляет долгоживущий объект с жесткими ссылками.

Ниже вы найдете спецификации среды и программное обеспечение, используемое для создания и выполнения этого симулятора утечки кучи Java.
  • ОС: Windows 7 @ 64-битная
  • Контейнер Java EE:  WildFly  8 Alpha 3
  • JVM: Oracle HotSpot 1.7 @ 64-разрядная с размером кучи Java 2 ГБ
  • IDE:  JBoss Developer Studio 7.0.0.GA
  • Мониторинг JVM:  JVisualVM
  • Анализатор утечек памяти JVM:  Plumbr 3.0
  • Тестирование производительности и нагрузки:  Apache JMeter 2.9
Plumbr скачать и установить \


Plumbr упакован как «пробная версия».
Это означает, что вы можете скачать полную версию бесплатно и определить, содержат ли ваши приложения утечку памяти. Расположение утечки памяти (уровень кода) потребует от вас или вашего клиента приобрести 
лицензионный план Plumbr  в соответствии с вашими потребностями.

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

  1. Войдите / зарегистрируйтесь на  https://portal.plumbr.eu/ . Это позволит вам загрузить клиент Plumbr.
  1. Распакуйте архив в любое место по вашему выбору (локальная среда, сервер разработки и т. Д.).

  2. Если ваше Java-приложение работает в ОС Windows, вы можете просто дважды щелкнуть файл plumbr.jar, расположенный в корневом каталоге Plumbr, или использовать следующую команду: java -jar plumbr.jar. Это запустит клиент Plumbr и позволит вам «присоединить» его к работающему процессу JVM. Другой подход состоит в том, чтобы просто отредактировать параметры запуска JVM вашего приложения и добавить следующий аргумент: -javaagent: <RUMT DIRECTORY PLUMBR> plumbr.jar. Я лично предпочитаю второй подход.

Теперь вернемся к нашему симулятору утечки памяти. Из приведенного ниже снимка вы заметите, что мы добавили ссылку агента Plumbr на аргументы запуска WildFly JVM непосредственно в IDE.

После перезапуска процесса JVM вы увидите похожее сообщение в начале стандартного выходного журнала:
************************************************************
* Plumbr (B1422) is attached.  *
* Running with JRE from …\jdk1.7.0_09\jre   *
* Your license is valid  *
*  for 20 more days   *
*  for Pierre-Hugues Charbonneau.  *
* Plumbr agent is connected to the Plumbr Portal.  *
* Open up https://portal.plumbr.eu to follow its progress. *
************************************************************
Это говорит нам о том, что Plumbr теперь активен и подключен к порталу Plumbr или серверу отчетов. Теперь перейдите на 
портал Plumbr
 и проверьте, правильно ли он получает данные от вашего процесса JVM.


Разминка симулятора утечки памяти


Теперь, когда агент Plumbr подключен, пришло время запустить наш симулятор утечки памяти.
Чтобы смоделировать интересную утечку памяти, мы будем использовать следующие спецификации нагрузочного тестирования:
  • JMeter будет настроен для выполнения нашего URI веб-службы REST jvmleak.
  • Наша группа потоков JMeter будет настроена для работы «навсегда» с 20 одновременными потоками.
  • JvisualVM и портал Plumbr будут использоваться для мониторинга использования кучи Java вместе с внутренним MBean-компонентом Plumbr.

Обратите внимание, что запуск JVisualVM не является обязательным, но я определенно рекомендую использовать его вместе с плагином браузера MBeans (надстройка для JVisualVM).
Это позволит вам отслеживать статус и прогресс агента Plumbr непосредственно из JVisualVM. Важно отметить, что вам нужно будет сгенерировать нагрузку и получить несколько итераций Full GC, прежде чем Plumbr сможет выявить истинные утечки памяти. Прошедшее время также будет зависеть от активности (нагрузки) и характера вашего приложения.


Поскольку в данный момент мы не запускаем JMeter, вы можете видеть, что Plumbr все еще находится в фазе WARMUP с завершением 10%.

Выполнение симулятора утечки памяти

Создание достаточного количества нагрузки для вашего приложения позволит Plumbr завершить фазу WARMUP довольно быстро.
Теперь мы можем видеть из нашего симулятора, что Plumbr находится в состоянии RUNNING и уже отслеживает несколько тысяч объектов. Однако на данный момент у нас не было Full GC, поэтому нам нужно подождать, пока не будут выполнены несколько итераций. Это позволит внутреннему вычислительному движку Plumbr выполнить оценку и потенциально сузить место утечки памяти.

Вы можете заметить, что количество объектов, отслеживаемых Plumbr, будет варьироваться между итерациями Full GC. Это связано с тем, что Plumbr обычно фокусируется только на «подозрительных» объектах, таких как объекты, способные выжить в больших коллекциях (Full GC).


После нескольких крупных коллекций Plumbr смог обнаружить потенциальную утечку памяти с вероятностью 98%.
Мы почти на месте … Важно отметить, что OutOfMemoryError не было сгенерировано. Утечка также может наблюдаться в JVisualVM, но она не столь очевидна в начале жизненного цикла нагрузочных испытаний.

Наконец, после более крупных коллекций Plumbr смог обнаружить утечку памяти с уровнем достоверности 100%.
Как вы можете видеть из снимков, JVisualVM позволил нам легко отслеживать изменения состояния кучи Java и Plumbr MBeans.


Вы также заметите следующее сообщение в стандартных журналах вывода.
15:22:41,270 INFO  [stdout] (Plumbr thread - 176) ******************************************************************************
15:22:41,271 INFO  [stdout] (Plumbr thread - 176) * Plumbr has found a memory leak.  *
15:22:41,271 INFO  [stdout] (Plumbr thread - 176) * Plumbr will now stop tracking to leave more resources for your application. *
15:22:41,271 INFO  [stdout] (Plumbr thread - 176) * You can find the detailed memory leak report by opening this url:  *
15:22:41,272 INFO  [stdout] (Plumbr thread - 176) * https://portal.plumbr.eu/report/5515  *
15:22:41,272 INFO  [stdout] (Plumbr thread - 176) ******************************************************************************
На данный момент мы должны дождаться, пока Plumbr проанализирует местоположение и тип обнаруженной утечки. Как только процесс анализа будет завершен, отчет будет создан и доступен на портале Plumbr. 

Отчет об утечке памяти Plumbr

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

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


Из вышеприведенного отчета мы видим, что Plumbr прекрасно смог идентифицировать утечку памяти.
Вы можете заметить, что отчет об утечке разделен на 4 основных раздела:
  • Заголовок содержит количество обнаруженных утечек, а также сведения об объеме памяти, занимаемой объектами утечки, и общую емкость кучи Java.
  • Тип объекта с утечкой : представляет  тип объекта  экземпляров, которые накапливаются между основными коллекциями с течением времени.
  • Место создания утечки : представляет собой вызывающую и Java-класс, в котором создаются утечки  .
  • Ссылки на память : представляет собой дерево ссылок на объекты, на которые по-прежнему ссылаются  или  хранятся текущие объекты  .

В нашем случае Plumbr смог определить точное местоположение нашей утечки памяти.

  • LongLivedObj действительно является ожидаемым типом объекта утечки.
  • JVMMemoryAllocator определенно является классом Java, в котором создается утечка.
  • ConcurrentHashMap — это реализованный «referencer» или контейнер.

Интересно, что Plumbr также смог определить еще одну потенциальную утечку внутри самой WildFly 8 Alpha 3 …

Теперь имейте в виду, что после создания отчета Plumbr волшебным образом не устранит утечку памяти за вас.
Вам нужно будет потратить некоторое время и просмотреть уязвимый код, особенно место, где создается утечка, и понять, почему на объекты все еще ссылаются. Plumbr сделает 50% + работы. Вам нужно будет позаботиться о другой половине и определить правильное исправление кода, обновление или исправление нарушающих API.

Заключительные слова

Я надеюсь, что вы оценили это руководство и обзор 
Plumbr 3.0  , имитируя настоящую утечку памяти в куче Java. Этот продукт выглядит многообещающе, и я определенно рекомендую вам попробовать Plumbr в вашей среде; особенно если вы подозреваете, что имеете дело с проблемами утечки памяти, влияющими на стабильность производственной среды. Спасибо команде разработчиков Plumbr!

Я с нетерпением жду ваших комментариев и, пожалуйста, поделитесь своим опытом с Plumbr.