1 В избранное 0 Ответвления 0

OSCHINA-MIRROR/vipshop-VJTools

Клонировать/Скачать
README.md 10 КБ
Копировать Редактировать Web IDE Исходные данные Просмотреть построчно История
gitlife-traslator Отправлено 26.11.2024 21:56 bc1b067

1. Обзор

VJMap для разных поколений (нового поколения, живущей зоны, старого поколения) — это инструмент для поиска причин медленного роста утечек памяти. Поскольку jmap -histo PID печатает статистическую информацию об объектах всего Heap, нам нужно специально изучить объекты OldGen и долгоживущие объекты в зоне Survivor, чтобы определить проблему.

Первоначальная идея VJMap основана на RTBJMap от Alibaba, который был обновлён для поддержки JDK8, фильтрации объектов в зоне Survivor и избегания проблем с выводом результатов.

Здесь есть практический пример: «[Только практика] Поиск проблем с быстрым ростом старого поколения JVM». В итоге проблема была связана с Jedis.

Обратите внимание: из-за принципа работы VJMap он поддерживает только CMS и ParallelGC, но не G1.

2. Использование

Скачать vjmap-1.0.8.zip (из Maven Central).

2.1 Примечания

  • Во время выполнения VJMap полностью останавливает приложение на некоторое время, что требует приостановки трафика!
  1. JAVA_HOME используется VJMap как JAVA_HOME/bin/java. Требуется как минимум JDK7, и JVM приложения должна использовать ту же версию JDK.

  2. VJMap зависит от JAVA_HOME/lib/sa-jdi.jar.

  3. Путь к JAVA_HOME определяется через переменную среды JAVA_HOME или, если она не определена, через команду «which java» для получения относительного пути.

  4. Для выполнения требуются права root (sudo -E vjmap.sh ...), аналогичные правам jmap -heap pid.

  5. Если соединение с процессом невозможно, можно попробовать выполнить jstack -F pid и jmap -heap pid для сравнения.

  6. При работе в контейнере требуется разрешение ptrace.

2.2 Основные команды

Для активных процессов используйте PID для идентификации процесса.

// Вывести полную статистику объектов в куче, отсортированную по общему размеру объекта:
./vjmap.sh -all PID > /tmp/histo.log

// Рекомендуется: вывести статистику объектов старого поколения, отсортированных по размеру oldgen, быстрее, чем -all, в настоящее время поддерживает только CMS:
./vjmap.sh -old PID > /tmp/histo-old.log

// Рекомендуется: вывести статистику объектов зоны Survivor, по умолчанию age>=3:
./vjmap.sh -sur PID > /tmp/histo-sur.log

// Рекомендуется: вывести статистику объектов зоны Survivor с минимальным возрастом 4:
./vjmap.sh -sur:minage=4 PID > /tmp/histo-sur.log

// Рекомендуется: вывести статистику объектов зоны Survivor только с возрастом 4:
./vjmap.sh -sur:age=4 PID > /tmp/histo-sur.log

Для файлов CoreDump:

./vjmap.sh -old ${path_to_java} ${path_to_coredump}

2.3 Только живые объекты

Принцип заключается в выполнении полного GC перед официальной статистикой.

./vjmap.sh -old:live PID > /tmp/histo-old-live.log

2.4 Фильтрация объектов по размеру, без отображения слишком маленьких объектов:

// Отфильтровать по размеру oldgen: отображать только объекты, занимающие более 1K в OldGen:
./vjmap.sh -old:minsize=1024 PID > /tmp/histo-old.log

2.5 Сортировка по имени класса, с фильтрацией по размеру и созданием отчётов для сравнения результатов:

./vjmap.sh -all:minsize=1024,byname PID > /tmp/histo.log

2.6 Другие примечания

  1. Неожиданное завершение

Выполнение VJMap занимает некоторое время. Если необходимо остановить его в середине процесса, используйте Ctrl+C или убейте PID VJMap. Если вы случайно использовали kill -9, целевой процесс Java останется заблокированным и больше не будет работать. В этом случае дважды выполните kill -SIGCONT $target_process_PID, чтобы перезапустить целевой процесс Java.

  1. Фрагментация OldGen

Если давно не было полных или CMS GC, в OldGen будет много живых регионов. Выполнение -all и -old может занять много времени. Например, первая часть -all Get Live Regions может быть очень медленной. Если не требуется намеренно наблюдать за мёртвыми объектами, сначала можно запустить полный GC, например, используя vjmap -all:live, или jmap -histo:live, или jcmd GC.run.

3. Примеры вывода

3.1 Статистика объектов зоны Survivor старше N

Survivor Object Histogram:

 #num  #count     #bytes #Class description
-----------------------------------------------------------------------------------
   1:      37         1k io.netty.buffer.PoolThreadCache$MemoryRegionCache$Entry
   2:       2         64 java.util.concurrent.locks.AbstractQueuedSynchronizer$Node
Total: 39/    1k over age 2

Траверсирование кучи заняло 1,3 секунды.

4. Дальнейший анализ с использованием Eclipse MAT

Если информации об объектах недостаточно для определения проблемы, необходимо использовать полный дамп Heap и анализировать отношения объектов для дальнейшего анализа. В MAT можно использовать OQL для фильтрации объектов старого поколения.

Предположим, что диапазон адресов OldGen составляет «0xfbd4c000» – «0xfce94050».

SELECT * FROM INSTANCEOF java.lang.Object t WHERE toHex(t.@objectAddress) <= "0xfce94050" AND toHex(t.@objectAddress) >= "0xfbd4c000"

Примечание: в настройках предпочтений MAT необходимо включить «Сохранять недоступные объекты».

Чтобы получить адрес старого поколения, можно сделать следующее:

  1. Добавить параметр запуска -XX:+PrintHeapAtGC, который будет печатать адрес при каждом GC.

  2. Использовать команду -address в VJMap, которая также будет печатать этот диапазон адресов.

  3. Быстро распечатать адреса всех поколений с помощью команды address в VJMap без длительной паузы.

./vjmap.sh -address PID

Вывод:

eden [0x0000000119000000,0x0000000119c4a258,0x0000000121880000) space capacity = 143130624, 9.003395387977907 used
from [0x0000000121880000,0x0000000121880000,0x0000000122990000) space capacity = 17891328, 0.0 used
to   [0x0000000122990000,0x0000000122990000,0x0000000123aa0000) space capacity = 17891328, 0.0 used
concurrent mark-sweep generation
free-list-space[ 0x0000000123aa0000 , 0x0000000139000000 ) space capacity = 357957632 used(4%)= 17024696 free= 340932936

В этом примере 0x123aa0000 является нижним пределом OldGen. Обратите внимание, что при использовании OQL необходимо удалить начальную строку чисел перед «0x».

5. Печать списка загруженных классов

./vjmap.sh -class PID

Чтобы соответствовать JDK8, информация о классе в Jar-файле больше не печатается.

6. Сравнение с TBJMap

  • Совместимость с JDK8
  • Новые функции: статистика объектов зоны Survivor старше N лет
  • Новые функции: печать диапазона адресов всех поколений для дальнейшего анализа в MAT
  • Улучшение производительности: прямой доступ к зонам Survivor и OldGen вместо использования обратного вызова Heap Visitor
  • Новые настройки: фильтрация объектов по занимаемой памяти, скрытие слишком мелких объектов
  • Новые настройки: сортировка объектов по именам классов для сравнения двух статистических результатов
  • Улучшения вывода: числа в отчёте унифицированы (k,m,g) и выровнены, отчёт OldGen по умолчанию сортируется по размеру объектов в OldGen

Опубликовать ( 0 )

Вы можете оставить комментарий после Вход в систему

1
https://api.gitlife.ru/oschina-mirror/vipshop-VJTools.git
git@api.gitlife.ru:oschina-mirror/vipshop-VJTools.git
oschina-mirror
vipshop-VJTools
vipshop-VJTools
master