Отладка странной утечки памяти-Java/Tomcat

Я испытываю очень странную проблему с приложением Java, работающим под Tomcat.

мы попытались обновить производственный код из нового нового производства в 1-недельном спринте, приложение работает в течение нескольких месяцев без икоты, а затем этот новый код заставляет наши серверы Linux начать обмен через некоторое время.

очень странно, что при просмотре VisualVM для использования памяти он никогда не превышает максимальный размер кучи, JVM не бросает OutOfMemory, машина только начинает менять местами, и JVM продолжает работать даже после этого.

Итак, кажется, что утечка памяти откуда-то, кажется, что это из нового кода, но странно, что это не внутри JVM, какие-либо идеи в том, как это отладить?

спасибо!

3 ответов


замена не является окончательным показателем утечки. Это результат низкой физической памяти. Используйте vmstat в Linux для получения использования подкачки. Попробуйте использовать другую машину, поэкспериментируйте с конфигурациями --размер подкачки, размер физической памяти, адресное пространство.

Если вы уверены, что проблема в вашей программе, попробуйте следующее:

  1. оцените медиану и пик памяти, что ваша программа должны использовать. Вы должны уметь учитывать все отклонения из этих показателей. Если не удается, перейдите к шагу 3.

  2. предполагая, что вы сделали шаг 1 правильно и смогли учесть все отклонения, вы можете исключить утечку (извините за такие неопределенные предложения, но отладка только так же хороша, как детектив). Теперь вы должны сосредоточиться на настройке GC. Во-первых, включите ведение журнала GC. Посмотрите, действительно ли ваша куча заполнена и где GC тратит большую часть своего времени на сбор. этой может быть хорошей отправной точкой для начала процессы оптимизации. Попробуйте проверить, помогает ли настройка параметров GC. Попробуйте экспериментировать с алгоритмами сбора, максимальными / минимальными размерами кучи, соотношениями генов и т. д. Экспериментируйте только тогда, когда вы исключили утечку (Шаг 1).

  3. предполагая, что вы сделали шаг 1 правильно и не смогли учесть все отклонения, вы можете предположить, что у вас есть утечка где-то. Используйте профилировщик памяти, чтобы увидеть, какие объекты вносят наибольший вклад в рост размера кучи. Оставьте профилировщик работать в течение длительного периода времени -- попросите вашу программу обработать некоторые запросы, которые она обычно ожидает получить, а затем оставить ее относительно изолированной после этого. Если уровень памяти продолжает расти, у вас может быть утечка где-то. Если нет, то это, вероятно, не утечка памяти. Можете ли вы указать часть вашей программы, которая может создавать их? Если да, попробуйте отправить несколько запросов, предназначенных только для этой части вашей программы. Воспроизводит ли он проблему детерминированно? Если нет, повторите шаг 3. Если да, используйте divide and conquer и apply Шаг 3, пока вы не найдете класс/метод, которые являются виновниками. Это может быть также определенная комбинация нескольких частей (что означает, что индивидуально они могут выглядеть невинными, но вместе они могут сформировать блестящий преступный синдикат).

надеюсь, это поможет, если нет, пожалуйста, оставьте комментарий к моему сообщению.

все самое лучшее на вашем упражнении!


Я бы предложил вам изучить создание кучи дампов без использования jvisualvm. Для Unix-основанных Oracle JVM это обычно делается путем отправки сигнала 3 в JVM с помощью kill.

для получения полной информации см. http://www.startux.de/index.php/java/45-java-heap-dumpyvComment45

затем вы можете увидеть, изменяются ли шаблоны.

Если вы не получите идеи из этого, то это может быть потому, что вы храните подстроку из очень большой оригинал string (который несет базовый массив строк) или потому, что вы держите ресурсы операционной системы, такие как открытые подключения к базе данных и т. д.

вы проверили, что ваш пул соединений выглядит хорошо?


Если вы не используете его, я бы рекомендовал использовать visual VM версии 1.3.2 и все плагины. Это большой скачок вверх от более ранних версий.

Что происходит с пространством Пермского поколения?

какие настройки памяти вы используете? Мин и Макс, конечно, но как насчет размера Пермского пространства?