Поиск кода, который заполняет PermGen мертвым кодом Groovy

У нас в течение некоторого времени наш экземпляр Glassfish отключается каждые две недели с java.lang.OutOfMemoryError: PermGen space . Я увеличил пространство PermGen до 512 МБ и начал использовать сброс памяти с помощью jstat -gc . Через две недели я придумал следующий график, который показывает, как пространство PermGen неуклонно увеличивается (единицы по оси x - минуты, ось y - КБ). Graph of increasing PermGen usage

Я пробовал поискать в Google какой-то инструмент профилирования, который мог бы точно определить ошибку, и в ветке SO упоминался jmap, который оказался весьма полезным. Из примерно 14000 строк, сброшенных из jmap -permstats $ PID , примерно 12500 содержат groovy / lang / GroovyClassLoader $ InnerLoader , указывая на некоторую утечку памяти из нашего собственного кода Groovy. или сам Groovy. Я должен указать, что Groovy составляет менее 1% соответствующей кодовой базы.

Пример вывода ниже:

class_loader    classes bytes   parent_loader   alive?  type

 3811    14830264      null      live    
0x00007f3aa7e19d20  20  164168  0x00007f3a9607f010  dead    groovy/lang/GroovyClassLoader$InnerLoader@0x00007f3a7afb4120
0x00007f3aa7c850d0  20  164168  0x00007f3a9607f010  dead    groovy/lang/GroovyClassLoader$InnerLoader@0x00007f3a7afb4120
0x00007f3aa5d15128  21  181072  0x00007f3a9607f010  dead    groovy/lang/GroovyClassLoader$InnerLoader@0x00007f3a7afb4120
0x00007f3aad0b40e8  36  189816  0x00007f3a9d31fbf8  dead    org/apache/jasper/servlet/JasperLoader@0x00007f3a7d0caf00
....

Итак, как мне продолжить, чтобы узнать больше о том, какой код вызывает это?

Из В этой статье Я сделал вывод, что наш код Groovy где-то динамически создает классы. И из дампа из jmap я вижу, что большинство мертвых объектов / классов (?) Имеют один и тот же parent_loader, хотя я не уверен, что это значит в данном контексте. Я не знаю, как действовать дальше.

Приложение

Для опоздавших стоит отметить, что принятый ответ не решает проблему . Он просто увеличивает период, необходимый до перезагрузки, в десять раз, не сохраняя так много информации о классе. Что на самом деле решило наши проблемы, так это избавление от кода, который их генерировал. Мы использовали структуру проверки (проектирование по контракту) OVal , в которой можно было написать собственные ограничения, используя Groovy в качестве аннотаций для методов и классов. Удаление аннотаций в пользу явных предварительных и пост-условий в простой Java было скучным, но это сделало свою работу. Я подозреваю, что каждый раз, когда проверялось ограничение OVal, создавался новый анонимный класс, и каким-то образом связанные данные класса вызывали утечку памяти.

10
задан oligofren 18 April 2015 в 12:13
поделиться