Как решить Metaspace OOM после многократного повторного развертывания веб-приложения в Tomcat?

Дера все,

Я использую openjdk 1.8.0_212-b04, Tomcat 8.0.21 и Red Hat 6.4.

И я настроил тестовое веб-приложение, чтобы убедиться, что после его повторного развертывания не будет такое сообщение:

WARNING: The web application [Test] appears to have started a thread named [test-job_Worker-1] but has failed to stop it. This is very likely to create a memory leak. Stack trace of thread

Вот параметр GC, который я использовал в тесте:

-Xms2G -Xmx4G 
-XX:MaxMetaspaceSize=1G -XX:CompressedClassSpaceSize=300 

-Dsun.rmi.dgc.client.gcInterval=9223372036854775807 
-Dsun.rmi.dgc.server.gcInterval=9223372036854775807 
-XX:+PrintGCDetails -XX:+PrintGCDateStamps -XX:GCLogFile Size=10M -XX:NumberOfGCLogFiles=5 -Xloggc:$LOG_HOME/gc-$START_TIME.log

И я использовал сценарий оболочки, чтобы продолжать касаться web.xml для повторного развертывания веб-приложения. Других трафиков/операций во время теста не было.

Вот граф метапространства VisualVM во время теста: введите здесь описание изображения

Как видно из рисунка: в точке 1 метапространство когда-нибудь сожмется, поэтому я думаю, что утечки памяти метапространства быть не должно.

Но в точке 2 Tomcat бросает метапространство OOM:

14-Jun-2019 09:26:32.184 SEVERE [ContainerBackgroundProcessor[StandardEngine[Catalina]]] org.apache.catalina.core.ContainerBase$ContainerBackgroundProcessor.run Unexpected death of background thread ContainerBackgroundProcessor[StandardEngine[Catalina]]
 java.lang.OutOfMemoryError: Metaspace
        at java.lang.ClassLoader.defineClass1(Native Method)
        at java.lang.ClassLoader.defineClass(ClassLoader.java:763)
        at java.security.SecureClassLoader.defineClass(SecureClassLoader.java:142)
        at org.apache.catalina.loader.WebappClassLoaderBase.findClassInternal(WebappClassLoaderBase.java:2472)
        at org.apache.catalina.loader.WebappClassLoaderBase.findClass(WebappClassLoaderBase.java:854)
        at org.apache.catalina.loader.WebappClassLoaderBase.loadClass(WebappClassLoaderBase.java:1274)
        at org.apache.catalina.loader.WebappClassLoaderBase.loadClass(WebappClassLoaderBase.java:1157)
        at org.apache.logging.log4j.status.StatusLogger.<init>(StatusLogger.java:108)
        at org.apache.logging.log4j.status.StatusLogger.<clinit>(StatusLogger.java:85)
        at org.apache.logging.log4j.web.Log4jServletContextListener.<clinit>(Log4jServletContextListener.java:44)
        at sun.reflect.NativeConstructorAccessorImpl.newInstance0(Native Method)
        at sun.reflect.NativeConstructorAccessorImpl.newInstance(NativeConstructorAccessorImpl.java:62)
        at sun.reflect.DelegatingConstructorAccessorImpl.newInstance(DelegatingConstructorAccessorImpl.java:45)

В точке 3 я нажал кнопку GC в VisualVM, метапространство фактически стало сжимаемым.

Я попытался добавить параметр: -XX:MaxMetaspaceFreeRatio=60, но все равно получил результат smae.

Вот граф метапространства GCeasy: введите здесь описание изображения

Вот журнал GC: Журнал GC

Спасибо за любые советы по устранению/устранению неполадок/отладке ошибки OOM.

Обновление 1: спасибо за предложение @samabcde, я добавил se.jiderhamn.classloader.leak.prevention.ClassLoaderLeakPreventor для проведения дополнительных тестов. Это помогает удалить некоторые переменные ThreadLocal и заставить веб-приложение работать больше времени.

14-Jun-2019 17:44:31.463 INFO [ContainerBackgroundProcessor[StandardEngine[Catalina]]] se.jiderhamn.classloader.leak.prevention.JULLogger.info Custom ThreadLocal of type org.springframework.core.NamedThreadLocal: Prototype beans currently in creation with value null will be remove()d from Thread[ContainerBackgroundProcessor[StandardEngine[Catalina]],5,main]

Но все же получил Metaspace OOM. введите здесь описание изображения


person Leon Chen    schedule 14.06.2019    source источник
comment
Пробовали ли вы решение из этого вопроса?   -  person samabcde    schedule 14.06.2019
comment
@samabcde: Спасибо, я попытался и обновил свой пост.   -  person Leon Chen    schedule 14.06.2019


Ответы (1)


Во время теста я увидел, что Metaspace почти достиг максимума, затем я остановился, чтобы переразвернуть веб-приложение, и сделал дамп кучи, поместил его под MAT для анализа.

Как и ожидалось, существует множество WebappClassLoader. Но я проверил Путь к корням GC | исключить все phatom/weak/soft. и т. д., это GC Root.

Я проверил Путь к корням GC | со всеми ссылками, то существует более одного корня GC. введите описание изображения здесь

Итак... эти WebappClassLoader на самом деле фатомные/слабые/мягкие. на который ссылаются другие объекты, он останется в куче на некоторое время, чтобы его можно было освободить.

Затем я добавляю параметр GC: -XX:SoftRefLRUPolicyMSPerMB=10, веб-приложение можно повторно развернуть более 1000 раз...

Итак, проблема решена!

PS. поскольку мы не будем в ближайшее время повторно развертывать веб-приложение в рабочей среде, мы не будем использовать -XX:SoftRefLRUPolicyMSPerMB=10.

person Leon Chen    schedule 15.06.2019