JavaRush /Курсы /JAVA 25 SELF /Инструменты анализа памяти: jmap, jvisualvm

Инструменты анализа памяти: jmap, jvisualvm

JAVA 25 SELF
64 уровень , 3 лекция
Открыта

1. jmap: командная магия

Автоматический сборщик мусора — это, конечно, прекрасно. Но даже Java-приложения могут «подтекать» (OutOfMemoryError), работать медленно или неожиданно тормозить из-за неправильного использования памяти. Причины могут быть разными:

  • Утечки памяти (memory leaks): объекты, которые должны были быть удалены, продолжают «жить».
  • Слишком большие объёмы данных в коллекциях.
  • Ошибки в логике кэширования.
  • Неосвобождённые ресурсы (например, потоки, файлы).

Ваша задача — научиться быстро находить такие проблемы. Иначе вы рискуете стать не программистом, а «разработчиком багов»!

Что такое jmap?

jmap — это утилита, входящая в стандартный комплект JDK. Она позволяет получить «снимок» (heap dump) памяти работающего Java-процесса. Этот снимок можно потом открыть в других инструментах и посмотреть, какие объекты занимают память, сколько их и кто на них ссылается.

Heap dump — это как фотография вашей кучи: все объекты, которые в ней есть, их типы, связи и размеры.

Как использовать jmap

Найдите PID процесса

Для начала нужно узнать идентификатор процесса (PID), в котором работает ваше Java-приложение. Это можно сделать разными способами:

Через jps (ещё одна утилита из JDK):

jps -l

Вы увидите список Java-процессов и их PID.

Через диспетчер задач (Task Manager) или ps в Linux.

Снимите дамп памяти

jmap -dump:format=b,file=heap.bin <PID>
  • format=b — бинарный формат (подходит для анализа).
  • file=heap.bin — имя файла, куда будет сохранён дамп.
  • <PID> — идентификатор процесса.

Пример:

jmap -dump:format=b,file=heap.bin 12345

Что делать с heap dump?
Обычно дамп анализируют в графических инструментах (например, jvisualvm или Eclipse MAT), потому что вручную в бинарном файле искать объекты — это уже высший пилотаж и немного мазохизм.

Другие возможности jmap

Просмотр статистики памяти:

jmap -heap <PID>

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

Список классов:

jmap -histo <PID>

Показывает статистику по классам: сколько объектов какого типа, общий размер.

Пример вывода:

# Объект Кол-во Байты
1
[C
1200 48000
2
java.lang.String
1000 32000
3
java.util.HashMap
200 12800

Это уже даёт представление: если у вас внезапно миллионы объектов какого-то типа — есть повод задуматься.

2. jvisualvm: визуальный анализатор памяти

jvisualvm — это графическая программа, входящая в JDK (посмотрите в папке bin). Она позволяет подключаться к локальным (и иногда удалённым) Java-процессам, мониторить их в реальном времени, снимать heap dump, смотреть статистику по памяти, потокам, GC, CPU и даже профилировать выполнение кода.

Если вы любите мышкой кликать и смотреть красивые графики — это ваш инструмент.

Как запустить jvisualvm

В командной строке (или через ярлык в Windows):

jvisualvm

Откроется окно, где вы увидите список всех локальных Java-процессов.

Основные функции jvisualvm

Мониторинг памяти в реальном времени

  • Выберите процесс в списке слева.
  • Перейдите на вкладку Monitor.
  • Вы увидите графики использования heap, CPU, количество потоков и классов.

Пример:

jvisualvm-monitor

Heap Dump (Снимок памяти)

  • На панели Monitor нажмите Heap Dump.
  • Через несколько секунд появится вкладка с анализом дампа.
  • Вы увидите список всех классов, количество объектов, их общий размер.

Поиск «тяжёлых» объектов

  • Сортируйте по размеру или количеству.
  • Если видите, что какой-то тип (например, ArrayList или String) занимает слишком много памяти — это повод для расследования.

Анализ ссылок (Reference Graph)

  • Кликните на класс — увидите, кто ссылается на объекты этого класса.
  • Можно «докопаться» до корня: почему объект не удаляется сборщиком мусора.

Анализ потоков

  • Вкладка Threads — показывает все потоки, их состояние.
  • Можно выявить «зависшие» или слишком активные потоки.

Профилирование

  • Вкладка Profiler — позволяет измерять, какие методы занимают больше всего времени или памяти.
  • Это уже глубокий анализ, но для поиска утечек памяти достаточно первых шагов.

3. Практика: анализируем утечку памяти

Пример кода с утечкой

import java.util.ArrayList;
import java.util.List;

public class MemoryLeakDemo {
    // Статическая коллекция — классика жанра!
    private static final List<String> bigList = new ArrayList<>();

    public static void main(String[] args) throws InterruptedException {
        for (int i = 0; i < 1_000_000; i++) {
            bigList.add("Строка номер " + i);
            if (i % 100_000 == 0) {
                System.out.println("Добавлено: " + i);
                Thread.sleep(500); // Даем время для анализа
            }
        }
        System.out.println("Готово! Не закрывайте приложение, откройте jvisualvm.");
        Thread.sleep(600_000); // 10 минут — время на анализ
    }
}

Что происходит?

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

Анализ через jvisualvm

  1. Запустите программу.
  2. Откройте jvisualvm и выберите процесс.
  3. На вкладке Monitor посмотрите график памяти.
    • Если всё хорошо, память после GC должна «освобождаться».
    • Если есть утечка, память только растёт.
  4. Сделайте Heap Dump.
  5. Посмотрите, какие объекты занимают больше всего памяти.
    • В нашем случае — java.util.ArrayList и java.lang.String.
  6. Кликните на объект — посмотрите, кто на него ссылается.
    • Увидите, что это статическое поле bigList.

Как исправить?

  • Удаляйте ненужные элементы из коллекций, ограничивайте их рост.
  • Зануляйте ссылки на тяжёлые объекты, когда они больше не нужны.
  • Не держите большие коллекции в static, если они не нужны постоянно.

4. Другие инструменты: Eclipse MAT, jconsole

Eclipse Memory Analyzer (MAT)

Eclipse MAT — это бесплатный, но при этом мощный инструмент для анализа heap dump. С его помощью можно увидеть, какие объекты занимают память и какие из них удерживают другие — так называемый retained set. Это позволяет точно определить, где прячется утечка.

Инструмент умеет строить подробные отчёты по подозрительным объектам (leak suspects) и спокойно справляется даже с гигантскими дампами размером в несколько гигабайт.

Работает всё просто: вы снимаете дамп памяти с помощью jmap или jvisualvm, открываете его в MAT, нажимаете кнопку Leak Suspects Report — и получаете готовый отчёт, где уже подсвечены потенциальные проблемы.

jconsole

jconsole — это простой и удобный инструмент для наблюдения за JVM в реальном времени. Он показывает, сколько памяти используется, насколько загружен процессор, сколько потоков работает и как ведёт себя сборщик мусора.

В отличие от более продвинутых инструментов вроде VisualVM, jconsole не анализирует heap dump, зато отлично подходит для быстрой диагностики — когда нужно одним взглядом понять, что сейчас происходит внутри приложения.

5. Типичные ошибки при анализе памяти

Ошибка №1: Снимаете дамп не того процесса. Часто на машине крутится много Java-приложений, и можно перепутать PID. Проверяйте через jps и убедитесь, что анализируете именно вашу программу.

Ошибка №2: Ожидаете увидеть «утечку» там, где её нет. GC может не сразу удалять объекты — иногда память «отпускается» только после Full GC. Не паникуйте, если после одной итерации память не освободилась — посмотрите на тренд.

Ошибка №3: Не учитываете влияние статических/кэшированных объектов. Многие утечки связаны с тем, что объекты хранятся в static-полях или глобальных коллекциях. Проверяйте, кто ссылается на «тяжёлые» объекты — это часто static.

Ошибка №4: Не используете профилирование в динамике. Heap dump — это хорошо, но иногда важно смотреть на рост памяти во времени (графики в jvisualvm). Если память стабильно растёт — есть повод для расследования.

Ошибка №5: Не удаляете слушателей/обработчики событий. Если вы подписались на событие, но не отписались — объект будет «жить» в памяти, даже если вы его больше не используете.

Совет: Не бойтесь экспериментировать с инструментами! Снимайте дампы, смотрите графики, кликайте по объектам — только так вы научитесь «чувствовать» память своей программы и быстро находить проблемы.

1
Задача
JAVA 25 SELF, 64 уровень, 3 лекция
Недоступна
Снятие дампа памяти с помощью jmap – Цифровой Слепок Медведя 🐻
Снятие дампа памяти с помощью jmap – Цифровой Слепок Медведя 🐻
1
Задача
JAVA 25 SELF, 64 уровень, 3 лекция
Недоступна
Просмотр статистики по классам через jmap – Инвентаризация Цифрового Зоопарка 🐒🐘🐆
Просмотр статистики по классам через jmap – Инвентаризация Цифрового Зоопарка 🐒🐘🐆
Комментарии
ЧТОБЫ ПОСМОТРЕТЬ ВСЕ КОММЕНТАРИИ ИЛИ ОСТАВИТЬ КОММЕНТАРИЙ,
ПЕРЕЙДИТЕ В ПОЛНУЮ ВЕРСИЮ