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