Сталкивались ли с утечками памяти?
Что проверяют
Понимаете ли вы, что сборщик мусора не спасает от утечек, и умеете ли искать их инструментами, а не угадывать. Следом обычно спрашивают, как отличить утечку от маленького хипа и что вы смотрели в дампе.
Как отвечать
Начните с определения: утечка в Java это объекты, которые больше не нужны, но остаются достижимыми от корней GC, поэтому сборщик не имеет права их удалить. Дальше свой случай по шагам: симптом, диагностика, причина, исправление. Пример должен быть вашим. Если в проде утечек не ловили, скажите честно и опишите, как воспроизводили её на стенде или как действовали бы.
Симптом: занятая память после полной сборки растёт от цикла к циклу, GC срабатывает всё чаще, в конце OutOfMemoryError: Java heap space или Metaspace.
- метрики: график памяти после GC через Micrometer и Grafana или
jstat -gcutil; - дамп:
-XX:+HeapDumpOnOutOfMemoryErrorзаранее в параметрах запуска, вручнуюjcmd <pid> GC.heap_dump; - анализ: Eclipse MAT, отчёт Leak Suspects и dominator tree, смотреть retained size и путь до GC root;
- профилирование: Java Flight Recorder с JDK Mission Control, async-profiler в режиме аллокаций.
Типичные причины: статическая коллекция или самописный кэш без вытеснения, неотписанные слушатели, ThreadLocal в пуле потоков, который никто не чистит, незакрытые ресурсы, утечка класслоадера при передеплое. Для памяти вне хипа пригодится -XX:NativeMemoryTracking=summary.
Исправление обычно скучное: кэш на Caffeine с maximumSize и expireAfterWrite, remove() для ThreadLocal в finally, try-with-resources.
Где спотыкаются
Говорят «в Java утечек не бывает, есть GC». Утечка здесь не про забытый free, а про лишнюю ссылку.
Путают утечку с нехваткой памяти. Если после сборки хип возвращается к одному уровню, это не утечка, а маленький -Xmx или всплеск нагрузки.
Лечат всё через WeakReference и WeakHashMap. Слабые ссылки не заменяют политику вытеснения, а в WeakHashMap слабый только ключ: если значение ссылается на свой ключ, запись не удалится никогда.