У нашего экземпляра стеклянной рыбы какое-то время выходили из строя каждые две недели с java.lang.OutOfMemoryError: PermGen space
.Я увеличил пространство PermGen до 512 МБ и начал использовать дамп памяти с jstat -gc
.Через две недели я придумал следующий график, который показывает, как пространство PermGen неуклонно увеличивается (единицы по оси x - минуты, по оси y - КБ).
Я попытался поискать какой-нибудь инструмент для профилирования, который мог бы точно определить ошибку и поток здесь, на упомянутом выше jmap, который оказался весьма полезным.Из приблизительно 14000 строк, сброшенных из jmap -permstats $PID
, приблизительно 12500 содержали groovy/lang/GroovyClassLoader$InnerLoader
, указывая на какую-то утечку памяти либо из нашего собственного кода Groovy, либо из самого Groovy.Я должен отметить, что Groovy составляет менее 1% соответствующей кодовой базы.
Пример выходных данных ниже:
class_loader classes bytes parent_loader alive? type
<bootstrap> 3811 14830264 null live <internal>
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
....
Итак, как я могу узнать больше о том, какой код вызываетthis?
Из этой статьи Я делаю вывод, что наш Groovy-код динамически создает классы где-то.И из дампа из jmap я вижу, что большинство мертвых объектов / классов (?) Имеют одинаковый parent_loader, хотя я не уверен, что это означает в этом контексте.Я не знаю, как действовать дальше.
Приложение
Для опоздавших стоит отметить, что принятый ответ не решает проблему .Он просто продлевает период, необходимый для перезагрузки, в десять раз, не сохраняя так много информации о классе.Что действительно исправило наши проблемы, так это избавление от кода, который его сгенерировал.Мы использовали платформу валидации (Design by contract) OVal , где можно было писать скрипты пользовательских ограничений, используя Groovy в качестве аннотаций для методов и классов.Удаление аннотаций в пользу явных предварительных и постусловий в простой Java было скучным, но это сделало свою работу.Я подозреваю, что каждый раз при проверке ограничения OVal создавался новый анонимный класс, и каким-то образом данные связанного класса вызывали утечку памяти.