В первом блоге этой мини-серии рассказывалось о создании очень неплотного примера приложения, чтобы мы могли исследовать методы решения проблем с кучей в серверных приложениях. Это демонстрирует большую проблему с шаблоном Producer-Consumer, а именно то, что потребительский код должен иметь возможность удалять элементы из очереди по крайней мере так же быстро, если не быстрее, чем производитель. Блог закончился тем, что я запустил пример кода и откинулся на спинку кресла, пока у него не осталось достаточно памяти для расследования. Пришло время заняться этим расследованием.
Если вы прочтете первую часть этого блога , то узнаете, что код с утечкой является частью приложения 1, которое записывает заказы на акции / акции в фиктивную базу данных с использованием шаблона Producer Consumer. Пример кода был написан так, чтобы содержать очень очевидный недостаток, а именно то, что OrderRecord
не может идти в ногу с OrderFeed
. Это означает, что очередь Order
становится все больше и больше, пока, наконец, приложение не исчерпает пространство кучи и не упадет. Дело в том, что, глядя на мой простой код, проблема должна быть очевидной, но что, если вы никогда не видели код раньше, и это огромный, сложный промышленный код, плюс нет простого потока мониторинга, чтобы следить за размером очереди или другие внутренние органы? Что вы делаете тогда?
Это три шага, необходимые для поиска проблемы с негерметичным приложением:
- Возьми дамп кучи текущего сервера.
- Используйте дамп кучи для создания отчета.
- Проанализируйте отчет.
Есть несколько инструментов, которые вы можете использовать для создания файла дампа кучи. Они включают:
- JConsole
- jvisualvm
- Eclipse Memory Analyzer Tool (MAT)
Взятие дампа кучи с помощью jconsole
Подключите jconsole
к вашему приложению. Нажмите на вкладку MBeans и откройте пакет com.sun.management
. Затем нажмите на HotSpotDiagnostic
. Откройте « Operations
и выберите dumpHeap
. Теперь вы увидите операцию dumpHeap
, которая принимает два параметра p0
и p1
. Введите имя файла для дампа кучи в поле редактирования p0
и нажмите кнопку dumpHeap.
Принимая кучу дамп с jvisualvm
При подключении к образцу кода щелкните правой кнопкой мыши свое приложение на левой панели «приложения» и выберите «Дамп кучи».
Обратите внимание, что если у вас есть удаленное подключение к вашему негерметичному серверу, jvisualvm сохранит файл дампа в каталоге /tmp
удаленного компьютера (при условии, что это окно Unix). Вам придется отправить этот файл по FTP на ваш компьютер для дальнейшего анализа.
Взятие свалки с MAT
Хотя jconsole
и jvisualvm являются частью инструмента JDK, MAT или анализатора памяти, это инструмент, основанный на затмении, который можно загрузить с eclipse org
Текущая версия MAT требует, чтобы на вашем компьютере был установлен 1.6 jdk. Если вы используете Java 1.7, не беспокойтесь, он установит 1.6 для вас и не испортит остальную часть вашего компьютера и версию 1.7 по умолчанию.
При использовании MAT нужно нажимать на «Aquire Heap Dump» и следовать инструкциям.
Удаленные подключения
Здесь следует отметить, что если вы пытаетесь выяснить, почему рабочий сервер падает, то вам, вероятно, придется подключиться удаленно, используя JMX, и для этого вам понадобятся следующие параметры командной строки, которые я повторил из моего предыдущего блога:
1
2
3
4
5
|
-Dcom.sun.management.jmxremote -Dcom.sun.management.jmxremote.port= 9010 -Dcom.sun.management.jmxremote.local.only= false -Dcom.sun.management.jmxremote.authenticate= false -Dcom.sun.management.jmxremote.ssl= false |
Когда брать свалку
Это займет немного мысли и немного удачи. Если вы получите свой дамп кучи слишком рано, то вы не сможете увидеть проблемы, потому что они маскируются легитимными, не протекающими экземплярами классов; однако, не ждите слишком долго, потому что для получения дампа кучи требуется память, и поэтому сам процесс создания дампа кучи может привести к сбою приложения.
Лучше всего присоединить jconsole
к вашему приложению и отслеживать его кучу, пока он не окажется на грани краха. Это легко заметить, поскольку все три индикатора кучи зеленого цвета:
Анализ дампа кучи
Вот тут-то и выходит MAT, поскольку он был разработан для анализа дампов кучи. Чтобы открыть и проанализировать дамп кучи, выберите File | Open Heap Dump
File | Open Heap Dump
После выбора файла дампа кучи вам будет предложено три варианта, как показано ниже:
Выберите: Отчет о подозрении на утечку . MAT теперь будет обрабатываться в течение нескольких секунд, прежде чем создать страницу, которая выглядит примерно так:
Круговая диаграмма демонстрирует, что в этом случае есть один главный подозреваемый утечка. Возможно, вы думаете, что это немного исправлено, ведь это пример кода, что вы ожидаете? Ну, да, в этом случае это очень ясно; подозреваемый «а» занимает 98,7 МБ, в то время как остальные объекты в памяти используют другие 1,5 МБ. Дело в том, что вы получаете круговые диаграммы с подозрением на утечку в реальных ситуациях, которые выглядят следующим образом.
Следующее, что нужно сделать, это копать немного глубже …
Следующая часть отчета, показанная выше, говорит нам, что существует LinkedBlockingQueue
который использует 98,46% памяти. Для дальнейшего изучения, нажмите Details>>
.
Это показывает, что проблема действительно заключается в нашем orderQueue
, к которому обращаются три объекта из моего предыдущего блога : OrderFeed
, OrderRecord
и OrderMonitor
и, как мы знаем из кода, содержит целую кучу объектов Order
.
Ну это все; MAT сказал нам, что у примера кода есть LinkedBlockingQueue
который использует все пространство кучи примера приложения, что вызывает огромные проблемы. Он не сказал нам, почему это происходит, и вы не можете этого ожидать. Это вопрос, как сказал бы Эркюль Пуаро Агаты Кристи , используя «маленькие серые клетки»…