使用泄漏的SSLSocketImpl分析堆转储

12

我有一个应用程序,在Amazon EC2上运行(使用多个AWS产品,如S3、DynamoDB等),并存在内存泄漏问题。我收集了一些堆转储,并通过Eclipse的Memory Analyzer Tool运行它们,该工具指出数百个可能是泄漏的sun.security.ssl.SSLSocketImpl实例(占用了数十MB的内存)。

然而,我遇到了难题,无法确定为什么这些SSLSocketImpl对象没有被释放。

堆转储中大多数SSLSocketImpl实例都有两个引用,一个来自java.lang.ref.Finalizer,另一个来自com.amazonaws.internal.SdkSSLSocket。我的堆转储中的Finalizer线程被报告为空闲状态,没有对象等待终结。但对于那些与泄漏的SSLSocketImpl对象相关的com.amazonaws.internal.SdkSSLSocket对象似乎已经被清理了。至少在MAT中的支配者视图中找不到它们。

我是分析Java堆转储的新手。接下来我应该寻找什么?如果Amazon的SdkSSLSocket对象确实被清理,为什么SSLSocketImpl对象没有被清理?

谢谢!


你找到了什么吗? - skirsch
从部署新实例开始,内存泄漏就不再是问题了,但我们从未真正找到问题的根源。这个问题已经被拖延了好几个月。 - ur-vogel
你使用了哪些EC2实例? - skirsch
我认为我们也有这个问题。我想知道升级sdk是否能解决这个问题。 - IcedDante
2个回答

3

这可能是由于未设置SSL会话缓存大小造成的,它默认为无限大,可能会消耗大量堆空间。设置javax.net.ssl.sessionCacheSize = 1000应该有所帮助。


3

我认为我也遇到了这个问题。在使用MAT(内存分析工具)时,我已经找到了问题的根源,或者至少是防止G1GC对tenured空间进行完整GC的方法。这是我查看的mat图表:

enter image description here

我的应用程序是一个简单的Spring boot响应式HTTP服务器,代理了相当数量的数据库读取调用。我在K8s上的docker容器中运行单个CPU,内存约为4GB。我将其增加到了8GB的内存,但仍然出现了问题。

我不认为这是内存泄漏,因为我可以观察到完整的GC能够清理tenured空间,只是需要一些时间。

我认为JDBC正在做的是,TCP连接被“Abandoned”后,它们会被降级到一个称为“AbandonedConnectionCleanupThread”的线程。

所以解决方案就是给JVM提供一个额外的CPU来服务于AbandonedConnectionCleanupThread。

当我这样做时,我的tenured空间大小从未增长过,g1_old_space的大小大约与tenured空间相同,但我的G1能够更有效地清理g1_old_space,因此长时间的应用程序暂停消失了,并且G1尊重我的-XX:MaxGCPauseMillis


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接