情况 - API 应用程序在 tomcat 上运行。每次我到达 API 终点时,“top”中的内存使用量都会增加一小部分。当它通过 ~35-40%(大约十几个请求)后,负载水平从 1% 变为 40+%,并且应用程序变得无响应(并且必须重新启动 tomcat/容器)。
我做了什么:
1. 在 1 个请求后进行堆转储,然后在 5-10 个请求后进行堆转储并进行比较。内存增长不在我的任何类中,而是在“int[]”和“java.lang”中。我对java内存管理了解不够,无法理解这种情况。
我使用
ps -eLf
监控线程计数/增长。没有什么可报告的。使用
jstat -gc
观察GC。输出如下所示:
(开始)
S0C S1C S0U S1U EC EU OC OU MC MU CCSC CCSU YGC YGCT FGC FGCT GCT
56832.0 57856.0 0.0 17266.5 157184.0 31716.8 546304.0 35573.4 40104.0 39112.5 4776.0 4474.5 7 1.669 2 0.251 1.921
(结束 - 在我失去联系之前)
S0C S1C S0U S1U EC EU OC OU MC MU CCSC CCSU YGC YGCT FGC FGCT GCT
28160.0 27648.0 0.0 0.0 217088.0 4693.9 546304.0 76262.8 404008.0 402586.8 139816.0 139470.6 40 2.595 13 2.859 5.455
再次 - 我对 java 内存管理了解不够,无法真正解释这些值。我可以看到主要的垃圾收集并没有花费太多时间,但肯定会发生。
还尝试(作为冰雹玛丽)使用
-XX:+UseG1GC
。没有真正的区别。随着使用率值变得疯狂,我观察了 CPU %/IOWait(通过顶部)。 CPU保持理性并且没有可测量的IOWait。还查看了
top -H
和 wchan。
还有其他值得一看的地方吗?看到这里明显被我忽略的东西了吗?
使用 Java 8 运行。最新 Tomcat 版本。 CentOS 7。(在 Docker 中测试运行)。
<小时/>附加
使用jstat -class
进行了一些测量,并对这些值感到好奇:
(开始)
Loaded Bytes . Unloaded Bytes Time
121699 122371.1 4 3.4 31.34
(完)
Loaded Bytes Unloaded Bytes Time
194495 191761.7 4 3.4 39.20
这是否表明我的应用程序已加载额外的 70K 类并且未卸载任何类?这是一个问题吗?
最佳答案
使用 jvisualvm
并远程连接(通过使用正确的 jmx 参数 https://docs.oracle.com/javase/8/docs/technotes/guides/visualvm/jmx_connections.html 启动 Tomcat 实例)。然后您将能够看到所有内容,包括堆内存等等。在您的情况下,您可能会耗尽堆内存,GC 会继续尝试释放内存,但由于内存泄漏而无法这样做,并且这种情况会无限期地重复,CPU 非常繁忙。
关于java - 调试可能存在内存泄漏的tomcat应用程序,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/60005835/