Не секрет, что GC освобождает только недостижимые объекты. Утечка в Java начинается там, где объект уже не нужен, но на него все еще есть цепочка ссылок от живого потока.
Симптомы обычно одинаковые: куча растет, GC срабатывает чаще, паузы увеличиваются, финал -
java.lang.OutOfMemoryError: Java heap space.Самые частые ловушки и фиксы:
🔳
static List/Map: добавили и не удалили - объекты остаются в памяти до выгрузки класса. Нужны remove/очистка, лимиты, иногда WeakHashMap.🔳non-static inner/anonymous class: неявно держит ссылку на внешний объект, особенно если внутри бесконечный
Thread.🔳listener/callback: подписались и не отписались - источник событий удерживает объект (UI, event bus).
🔳ThreadLocal в пуле потоков:
set() без remove().🔳кэш на
HashMap без maxSize/TTL: используйте политики вытеснения (Guava Cache, Caffeine)В целом вывод такой, что нужно смотреть график heap в Grafana, снимать heap dump (jmap), в Eclipse MAT запускать Leak Suspects и проверять цепочки удерживающих ссылок.
📎 Читать на Хабре: https://habr.com/ru/companies/spring_aio/articles/1022018/
