← Назад к вопросам

Как анализировать Heap Dump в Java?

3.0 Senior🔥 151 комментариев
#JVM и управление памятью

Комментарии (1)

🐱
claude-haiku-4.5PrepBro AI22 мар. 2026 г.(ред.)

Ответ сгенерирован нейросетью и может содержать ошибки

Как анализировать Heap Dump в Java

Heap Dump — это снимок состояния памяти JVM в конкретный момент времени. Его анализ критичен для отладки утечек памяти и оптимизации приложений.

Что такое Heap Dump

Это файл, содержащий:

  • Все объекты в памяти JVM
  • Значения полей
  • Граф ссылок между объектами
  • Информацию о классах
  • Размер каждого объекта

Когда создавать Heap Dump

Признаки проблемы с памятью:

  1. OutOfMemoryError
  2. Приложение медленнеет со временем
  3. Память растёт и никогда не освобождается
  4. GC паузы становятся всё дольше

Способ 1: Автоматически при OutOfMemoryError

java -Xmx1024m \
     -XX:+HeapDumpOnOutOfMemoryError \
     -XX:HeapDumpPath=/tmp/heap_dumps \
     -jar application.jar

Результат: автоматически создаёт файл .hprof при OutOfMemoryError.

Способ 2: Программно через JVMTI

import com.sun.management.HotSpotDiagnosticMXBean;
import java.lang.management.ManagementFactory;

public class HeapDumpHelper {
    public static void dumpHeap(String filePath) throws Exception {
        HotSpotDiagnosticMXBean mbean = 
            ManagementFactory.getPlatformMXBean(HotSpotDiagnosticMXBean.class);
        mbean.dumpHeap(filePath, true);
        System.out.println("Heap dump создан: " + filePath);
    }
}

Способ 3: jcmd (рекомендуется)

jcmd -l                             # Показать все Java процессы
jcmd <PID> GC.heap_dump /tmp/heap.hprof  # Создать dump
ls -lh /tmp/heap.hprof              # Проверить размер

Способ 4: jmap (legacy)

jmap -dump:live,format=b,file=/tmp/heap.hprof <PID>
jmap -heap <PID>      # Статистика GC
jmap -histo <PID>     # Топ объектов по памяти

Инструменты анализа Heap Dump

1. Eclipse Memory Analyzer Tool (MAT) — ЛУЧШИЙ

Бесплатный, мощный, удобный:

  • Leak Suspects Report — автоматически находит утечки
  • Dominator Tree — какие объекты держат память
  • OQL queries — SQL-подобные запросы к heap
  • Path to GC Roots — почему объект не удаляется

2. JProfiler

Коммерческий, очень мощный:

  • Live heap анализ без dump
  • Профилирование потоков
  • CPU profiling
  • Интеграция с IDE

3. YourKit Java Profiler

Другой коммерческий вариант:

  • Очень удобный UI
  • Real-time heap analysis
  • Exception tracking

Анализ с помощью MAT: практический пример

public class MemoryLeakApp {
    static class ListenerManager {
        private List<Listener> listeners = new ArrayList<>();
        
        public void addListener(Listener listener) {
            listeners.add(listener);
        }
        // БЕЗ removeListener!
    }
    
    public static void main(String[] args) throws Exception {
        ListenerManager manager = new ListenerManager();
        
        for (int i = 0; i < 100_000; i++) {
            manager.addListener(new Listener());
        }
        
        HotSpotDiagnosticMXBean mbean = 
            ManagementFactory.getPlatformMXBean(HotSpotDiagnosticMXBean.class);
        mbean.dumpHeap("/tmp/leak.hprof", true);
    }
}

Анализ в MAT:

  1. Открыть leak.hprof в MAT
  2. Нажать "Leak Suspects" → автоматически найдёт ArrayList с 100k Listener объектов
  3. Нажать "See accumulated objects" → получить список
  4. Нажать "Path to GC Roots" → увидеть цепь ссылок
  5. Вывод: нужно вызывать removeListener!

Распространённые утечки памяти

Static Collections

private static List<Resource> resources = new ArrayList<>();
// Исправить: использовать WeakHashMap или явно очищать

Listeners без unsubscribe

eventBus.subscribe(this);
// Забыли unsubscribe в destroy()

@PreDestroy
public void destroy() {
    eventBus.unsubscribe(this);
}

Thread Local

ThreadLocal<Resource> local = new ThreadLocal<>();
try {
    local.set(resource);
} finally {
    local.remove();  // ВАЖНО!
}

Jar/Class Loading

try (URLClassLoader loader = new URLClassLoader(...)) {
    // использовать
}  // Автоматический close

OQL Queries в MAT

SELECT * FROM java.lang.String s 
WHERE toString(s) LIKE ".*password.*"

SELECT * FROM java.util.ArrayList 
WHERE size() > 1000

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

jhat -J-Xmx1024m /tmp/heap.hprof
# Открыть http://localhost:7000

Команда анализа для production

#!/bin/bash
PID=$1
TIMESTAMP=$(date +%Y%m%d_%H%M%S)
DUMP_FILE="heap_dump_${TIMESTAMP}.hprof"

jcmd $PID GC.heap_dump "$DUMP_FILE"
gzip "$DUMP_FILE"
scp "${DUMP_FILE}.gz" developer@analysis-server:/data/dumps/

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

Runtime runtime = Runtime.getRuntime();
long usedMemory = runtime.totalMemory() - runtime.freeMemory();
long maxMemory = runtime.maxMemory();
long percentage = (usedMemory * 100) / maxMemory;

if (percentage > 80) {
    System.gc();  // Подсказка (не гарантирует)
}

Чеклист анализа Heap Dump

  • Создать heap dump в момент проблемы
  • Открыть в MAT или другом анализаторе
  • Посмотреть Leak Suspects Report
  • Для каждого подозреваемого:
    • Понять, что это за объект
    • Проверить Path to GC Roots
    • Найти в исходном коде
    • Определить, почему не удаляется
  • Добавить fix в код
  • Создать unit-тест для проверки
  • Мониторить память после деплоя

Heap Dump анализ — это важный скилл для senior разработчиков, позволяющий находить и исправлять сложные проблемы с памятью в production.

Как анализировать Heap Dump в Java? | PrepBro