Ответ
План действий при OutOfMemoryError:
1. Сбор данных (не перезапускать приложение сразу!):
- Автоматический дамп кучи: Запускайте JVM с флагами для автоматического снятия дампа при ошибке.
java -XX:+HeapDumpOnOutOfMemoryError -XX:HeapDumpPath=/path/to/dump.hprof -Xmx1g -jar app.jar - Ручной дамп: Если приложение еще живо, снимите дамп утилитой
jmap.jmap -dump:live,format=b,file=heap.hprof <pid>
2. Анализ дампа с помощью профилировщика:
- Eclipse MAT (Memory Analyzer Tool) или VisualVM для анализа «тяжелых» объектов и цепочек ссылок, удерживающих память.
- Ищите: свои классы, занимающие большую часть памяти; массивы-гиганты; коллекции без ограничения размера.
3. Поиск типичных причин:
- Утечка памяти: Объекты, на которые остаются ссылки, но не используются (часто в статических полях, кешах, слушателях событий).
- Чрезмерное использование памяти: Легитимные структуры данных, размер которых не контролируется (например, загрузка всего файла в память).
- Метаданные классов (Metaspace):
OutOfMemoryError: Metaspace— слишком много классов загружено (часто в серверах приложений, из-за утечки ClassLoader).
4. Решения и профилактика:
- Исправьте утечку: Уберите ненужные ссылки, используйте
WeakReference/SoftReferenceдля кешей. - Настройте JVM: Увеличьте
-Xmx(куча),-XX:MaxMetaspaceSize(метаданные). - Используйте правильные структуры данных: Например,
ArrayListвместоLinkedListдля хранения примитивов, если важен объем памяти. - Мониторинг: Настройте мониторинг потребления памяти (JMX, Prometheus) и GC-логи (
-Xlog:gc*).