Telegram Group & Telegram Channel
Задача для опытных Java-разработчиков: «Призрачная утечка памяти в продакшене»

🧠 Уровень: Senior Java / JVM Internals
🎯 Цель: Найти источник утечки памяти в долгоживущем Java-сервисе и объяснить поведение GC

📍 Ситуация:

У вас есть Java-сервис (Spring Boot), который стабильно работает 5–6 часов, а потом начинает резко тормозить.
Мониторинг показывает рост heap usage почти до лимита, несмотря на регулярные GC-сборки.

Интересные факты:
- GC срабатывает часто, но не очищает больше 20–30% хипа
- Не происходит OutOfMemoryError, но приложение начинает "фризить"
- Подозрения падают на кэш, но размер кэша — ограничен (Caffeine, maxSize=5000)
- Все коллекции под контролем, слабые ссылки используются
- Нет утечек в логах, нет Thread`-leak по `jstack

🧩 Задача:

1. Где искать утечку, если GC работает, но память не освобождается?
2. Почему слабые ссылки не помогают?
3. Как поведение ClassLoader может влиять на утечку?
4. Какой инструмент использовать для анализа "живых" объектов в памяти?
5. Как бы вы реализовали периодический аудит памяти в проде без перезапуска?
6. Покажи, как сработает jmap, jcmd, MAT или VisualVM для выявления источника


💡 Подсказка:
Некоторые библиотеки (особенно с рефлексией, динамической загрузкой классов и кэшем) создают утечки через неудаляемые ссылки на ClassLoader, особенно в сочетании с ThreadLocal, ScheduledExecutorService, Class.forName, URLClassLoader.

🛠 Решение:

1. Снимаем дамп памяти:

jmap -dump:format=b,file=heap.bin <PID>

или

jcmd <PID> GC.heap_dump heap.bin


2. Анализируем в Eclipse MAT:
- Сортируем объекты по retained size
- Видим ThreadLocalMap, ClassLoader, Class → strong references остаются даже после GC
- Причина — статические поля/синглтоны держат ссылки на классы, которые не выгружаются

3. Проверяем код:
- Использовался Class.forName(...) в плагин-системе
- Загруженные классы не выгружались, т.к. на них ссылается пул потоков

4. Решения:
- Использовать WeakReference к загруженным классам
- Вызывать shutdownNow() и вручную очищать ThreadLocal.remove()
- Избегать глобальных синглтонов со ссылками на классы, загружаемые динамически

5. Профилактика:
- Включить периодический jcmd GC.class_histogram
- Встроить /heapdump endpoint для отладки в проде (под защищённым доступом)

📌 Вывод:
Даже при работающем GC утечка возможна, если в памяти удерживаются ссылки через ThreadLocal, ClassLoader, или пула потоков. Это не очевидно и не вызывает OOM, но "раздувает" хип и убивает производительность.

💬 Идеальный вопрос для собеседования на позицию Java-сеньора с уклоном в JVM-интерны.

@javatg



tg-me.com/javatg/1864
Create:
Last Update:

Задача для опытных Java-разработчиков: «Призрачная утечка памяти в продакшене»

🧠 Уровень: Senior Java / JVM Internals
🎯 Цель: Найти источник утечки памяти в долгоживущем Java-сервисе и объяснить поведение GC

📍 Ситуация:

У вас есть Java-сервис (Spring Boot), который стабильно работает 5–6 часов, а потом начинает резко тормозить.
Мониторинг показывает рост heap usage почти до лимита, несмотря на регулярные GC-сборки.

Интересные факты:
- GC срабатывает часто, но не очищает больше 20–30% хипа
- Не происходит OutOfMemoryError, но приложение начинает "фризить"
- Подозрения падают на кэш, но размер кэша — ограничен (Caffeine, maxSize=5000)
- Все коллекции под контролем, слабые ссылки используются
- Нет утечек в логах, нет Thread`-leak по `jstack

🧩 Задача:

1. Где искать утечку, если GC работает, но память не освобождается?
2. Почему слабые ссылки не помогают?
3. Как поведение ClassLoader может влиять на утечку?
4. Какой инструмент использовать для анализа "живых" объектов в памяти?
5. Как бы вы реализовали периодический аудит памяти в проде без перезапуска?
6. Покажи, как сработает jmap, jcmd, MAT или VisualVM для выявления источника


💡 Подсказка:
Некоторые библиотеки (особенно с рефлексией, динамической загрузкой классов и кэшем) создают утечки через неудаляемые ссылки на ClassLoader, особенно в сочетании с ThreadLocal, ScheduledExecutorService, Class.forName, URLClassLoader.

🛠 Решение:

1. Снимаем дамп памяти:


jmap -dump:format=b,file=heap.bin <PID>

или

jcmd <PID> GC.heap_dump heap.bin


2. Анализируем в Eclipse MAT:
- Сортируем объекты по retained size
- Видим ThreadLocalMap, ClassLoader, Class → strong references остаются даже после GC
- Причина — статические поля/синглтоны держат ссылки на классы, которые не выгружаются

3. Проверяем код:
- Использовался Class.forName(...) в плагин-системе
- Загруженные классы не выгружались, т.к. на них ссылается пул потоков

4. Решения:
- Использовать WeakReference к загруженным классам
- Вызывать shutdownNow() и вручную очищать ThreadLocal.remove()
- Избегать глобальных синглтонов со ссылками на классы, загружаемые динамически

5. Профилактика:
- Включить периодический jcmd GC.class_histogram
- Встроить /heapdump endpoint для отладки в проде (под защищённым доступом)

📌 Вывод:
Даже при работающем GC утечка возможна, если в памяти удерживаются ссылки через ThreadLocal, ClassLoader, или пула потоков. Это не очевидно и не вызывает OOM, но "раздувает" хип и убивает производительность.

💬 Идеальный вопрос для собеседования на позицию Java-сеньора с уклоном в JVM-интерны.

@javatg

BY Java


Warning: Undefined variable $i in /var/www/tg-me/post.php on line 283

Share with your friend now:
tg-me.com/javatg/1864

View MORE
Open in Telegram


Java Telegram | DID YOU KNOW?

Date: |

Tata Power whose core business is to generate, transmit and distribute electricity has made no money to investors in the last one decade. That is a big blunder considering it is one of the largest power generation companies in the country. One of the reasons is the company's huge debt levels which stood at ₹43,559 crore at the end of March 2021 compared to the company’s market capitalisation of ₹44,447 crore.

The global forecast for the Asian markets is murky following recent volatility, with crude oil prices providing support in what has been an otherwise tough month. The European markets were down and the U.S. bourses were mixed and flat and the Asian markets figure to split the difference.The TSE finished modestly lower on Friday following losses from the financial shares and property stocks.For the day, the index sank 15.09 points or 0.49 percent to finish at 3,061.35 after trading between 3,057.84 and 3,089.78. Volume was 1.39 billion shares worth 1.30 billion Singapore dollars. There were 285 decliners and 184 gainers.

Java from pl


Telegram Java
FROM USA