Java 在Tomcat中多次重新部署web应用程序后,如何解决元空间OOM问题?

Java 在Tomcat中多次重新部署web应用程序后,如何解决元空间OOM问题?,java,out-of-memory,tomcat8,metaspace,Java,Out Of Memory,Tomcat8,Metaspace,德拉,所有人 我使用的是openjdk 1.8.0212-b04、Tomcat 8.0.21和Red Hat 6.4 我已经调整了测试web应用程序,确保重新部署后不会出现此类消息: 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 memo

德拉,所有人

我使用的是openjdk 1.8.0212-b04、Tomcat 8.0.21和Red Hat 6.4

我已经调整了测试web应用程序,确保重新部署后不会出现此类消息:

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
我使用了一个shell脚本,不断接触web.xml来重新部署web应用程序。测试期间没有其他交通/操作

以下是测试期间VisualVM的元空间图:

如图所示:在第1点,元空间有时会收缩,因此我认为应该没有元空间内存泄漏

但在第2点,Tomcat抛出了元空间:

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)
但仍然有元空间。

在一次测试中,我看到元空间几乎达到最大值,然后我停下来重新部署web应用程序,并进行堆转储,将其放在MAT下进行分析

正如预期的那样,有许多WebappClassLoader。 但我检查了它的GC根路径|排除所有phatom/weak/soft。etc引用,它是它的GC根

我检查了它到GC根的路径|使用所有引用,然后有多个GC根。

所以。。。那些WebappClassLoader实际上是phatom/weak/soft。如果被其他对象引用,它将在堆中保留一段时间以释放

然后我添加GC参数:-XX:SoftRefLRUPolicyMSPerMB=10,web应用程序可以重新部署1000次以上

问题解决了


另外,由于我们不会在短时间内在生产环境中重新部署web应用程序,因此我们不会使用-XX:SoftRefLRUPolicyMSPerMB=10。

您是否尝试了来自的解决方案?@samabcde:谢谢,我尝试过,并更新了我的帖子。
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]