Ответ
Анализ следует начать со сбора и изучения дампа памяти (heap dump), созданного в момент ошибки OOME.
План действий:
- Включите автоматическое создание дампа при OOME, добавив в аргументы JVM:
-XX:+HeapDumpOnOutOfMemoryError -XX:HeapDumpPath=/path/to/dumps - Проанализируйте дамп с помощью профилировщиков:
- Eclipse Memory Analyzer (MAT) — мощный инструмент для поиска утечек.
- VisualVM или JProfiler — для интерактивного анализа. В них нужно:
- Найти объекты, занимающие наибольший объем памяти (вкладка Histogram или Biggest Objects).
- Построить путь до GC Root для этих объектов, чтобы понять, что удерживает их в памяти.
- Искать паттерны утечек, например, коллекции, которые бесконечно растут.
- Изучите логи сборки мусора (GC logs), включив их:
-Xlog:gc*:file=gc.log -XX:+UseGCLogFileRotation -XX:NumberOfGCLogFiles=5 -XX:GCLogFileSize=10MОбратите внимание на частоту и длительность сборок мусора, особенно Full GC.
Пример кода с потенциальной утечкой (статическая коллекция):
public class LeakyCache {
private static final Map<String, byte[]> CACHE = new HashMap<>();
public void storeData(String id, byte[] data) {
// Данные добавляются, но никогда не удаляются -> утечка
CACHE.put(id, data);
}
}
Дополнительные шаги: проверка настроек памяти (-Xmx, -Xms), мониторинг метрик (через JMX/Prometheus) и анализ кода на наличие подобных паттернов.