Профилирование памяти: как определить, какое приложение / пакет потребляет слишком много памяти - PullRequest
4 голосов
/ 02 июня 2010

У меня есть ситуация на работе, когда мы запускаем сервер Java EE с несколькими приложениями, развернутыми на нем. В последнее время у нас были частые исключения OutOfMemoryException. Мы подозреваем, что некоторые приложения могут плохо работать, могут быть утечки или что-то в этом роде.

Проблема в том, что мы не можем сказать, какой именно. Мы запустили некоторые профилировщики памяти (например, YourKit), и они довольно хорошо говорят, какие классы используют больше всего памяти. Но они не показывают отношения между классами, поэтому у нас возникает такая ситуация: мы видим, что, скажем, существует множество строк и массивов int и записей HashMap, но мы не можем сказать, какое приложение или пакет они родом из.

Есть ли способ узнать, откуда берутся эти объекты, поэтому мы можем попытаться определить пакеты (или приложения), которые выделяют больше всего памяти?

Ответы [ 3 ]

3 голосов
/ 02 июня 2010

В этой ситуации можно сделать несколько вещей:

  • Сконфигурируйте сервер приложений Java EE для создания дампа кучи на OOME . Эта функция доступна через параметр JVM с 1,5 дней. Как только дамп получен, его можно анализировать в автономном режиме, используя такие инструменты, как Eclipse MAT . Важной частью является выяснение дерева доминирующих.
  • Выполнить профилирование памяти на тестовом сервере; Netbeans хорош в этом. Это должно занять больше времени, чем первое, когда дело доходит до анализа первопричины, поскольку должны присутствовать точные условия сбоя выделения памяти. Если у вас есть автоматизированные интеграционные / функциональные тесты, то выявление первопричины будет проще. Хитрость заключается в том, чтобы периодически получать дампы кучи и анализировать классы, которые способствуют увеличению потребления кучи. Это не обязательно может быть утечка - это может быть случай недостаточного размера кучи.
0 голосов
/ 12 октября 2010

Что мне показалось полезным:

jmap -J-d64 -histo $PID

(убрать опцию -J-d64 для 32-битной арки)

Это выведет что-то вроде этого:

num     #instances         #bytes  class name
----------------------------------------------
1:       4040792     6446686072  [B
2:       3420444     1614800480  [C
3:       3365261      701539904  [I
4:       7109024      227488768  java.lang.ThreadLocal$ThreadLocalMap$Entry
5:       6659946      159838704  java.util.concurrent.locks.ReentrantReadWriteLock$Sync$HoldCounter

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

Это приостановит виртуальную машину только на короткое время, даже для больших куч, поэтому вы можете безопасно сделать это в производственном режиме (в непиковые часы, надеюсь, :))

0 голосов
/ 02 июня 2010

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

...