我有一个在亚马逊EC2上运行的应用程序(使用几个亚马逊网络服务产品,如S3、DynamoDB等)并且有一个内存泄漏。我收集了一些堆转储,并通过Eclipse的Memory Analyzer工具运行它们,该工具将数百个sun.security.ssl.SSLSocketImpl实例(占用数十MB内存)定位为可能的泄漏。
然而,我很难弄清楚为什么这些SSLSocketImpl对象还没有被处理掉。
转储中的大多数SSLSocketImpl实例都有两个引用,一个来自java.lang.ref.Finalizer,另一个来自com.amazonaws.internal.SdkSSLSocket。堆转储中的终结器线程被报告为空闲,没有对象等待终结化。但是,引用泄漏的SSLSocketImpl对象的com.amazonaws.internal.SdkSSLSocket对象似乎已被清除。至少,我在堆转储(MAT中的Dominator视图)中找不到它们。
我是分析java堆转储的新手。下一步我应该寻找什么?如果亚马逊SdkSSLSocket对象确实已经被清理,为什么SSLSocketImpl对象没有也被清理呢?
谢谢!
发布于 2020-05-20 14:56:57
我想我也遇到了这个问题。在对MAT进行了一些修改之后,我能够找出发生了什么事情的根本原因,或者至少可以阻止G1GC在永久空间上执行完整的GC。这是我看过的垫子图:

我的应用程序是一个简单的Spring boot反应式http服务器,它代理了相当数量的数据库读取调用。我在K8s上的docker容器中运行单CPU,内存约为4 4GB。我将内存增加了一倍至8 8GB,但仍然看到了问题。
我不相信这是一个内存泄漏,因为我可以观察到完整的GC能够清理永久空间,这只需要一段时间。
我相信JDBC正在做的是,当TCP连接被放弃时,它们被降级到一个叫做 AbandonedConnectionCleanupThread的线程中。
So what the solution turned out to be was just giving the JVM an extra CPU to service the AbandonedConnectionCleanupThread。
一旦我这样做了,我的永久空间大小就再也没有增长过,g1_old_space将以永久空间的大小增长,但是我的G1能够比永久空间更有效地清理g1_old_space,所以应用程序暂停消失了,并且G1尊重我的As
发布于 2019-06-24 20:15:11
这可能是因为没有设置SSL会话缓存大小,默认情况下它是无限大的,最终可能会消耗大量的堆空间。设置javax.net.ssl.sessionCacheSize = 1000应该会有所帮助。
https://stackoverflow.com/questions/40999496
复制相似问题