gpt4 book ai didi

java - Tomcat多次重新部署Web应用后如何解决Metaspace OOM?

转载 作者:塔克拉玛干 更新时间:2023-11-02 08:30:46 27 4
gpt4 key购买 nike

所有的一切,

我正在使用 openjdk 1.8.0_212-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的元空间图: enter image description here

如图所示:在第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 点,我在 VisualVM 中单击了 GC 按钮,元空间实际上是可收缩的。

我尝试添加参数:-XX:MaxMetaspaceFreeRatio=60,但仍然得到了 smae 结果。

这是GCeasy的元空间图: enter image description here

这是 GC 日志: GC Log

感谢您提供解决/故障排除/调试 OOM 错误的任何建议。

更新 1:感谢@samabcde 的建议,我添加了 se.jiderhamn.classloader.leak.prevention.ClassLoaderLeakPreventor 来做更多的测试。它有助于删除一些 ThreadLocal 变量并使 Web 应用程序保持更多时间。

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。 enter image description here

最佳答案

测试时,看到Metaspace快满了,就停下来重新部署web应用,做了一个heap dump,放在MAT下分析。

不出所料,有很多WebappClassLoader。但我检查了它是 GC Roots 的路径 |排除所有幻影/弱/软。 etc 引用,它是 GC Root。

我检查了它的 GC Roots 路径 |有了所有的引用,那么就有不止一个 GC Roots。 enter image description here

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

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

那么问题就解决了!

附言。由于我们不会在生产环境短时间内重新部署web应用,所以我们不会使用-XX:SoftRefLRUPolicyMSPerMB=10。

关于java - Tomcat多次重新部署Web应用后如何解决Metaspace OOM?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/56590702/

27 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com