Sun的Java SSL实现是否泄漏内存?

mal*_*ere 11 java ssl memory-leaks

我有一个服务器组件,我正在尝试加载测试.与服务器的所有连接都使用TLS 1.0.我有一个简单的测试程序,基本上可以在我想要的多个线程上执行此操作:

Full TLS handshake to the server
send a request
read reply
close connection
repeat ad nauseam
Run Code Online (Sandbox Code Playgroud)

我的虚拟机如下:

Java(TM) SE Runtime Environment (build 1.6.0_16-b01)
Java HotSpot(TM) Server VM (build 14.2-b01, mixed mode)
Run Code Online (Sandbox Code Playgroud)

我有内存泄漏.当我大量测试我的服务器时,我的内存占用每秒增加大约1兆,这使得它在15-20分钟后就会阻塞OutOfMemoryException.

我在Netbean的分析器中运行它,它表明内存的增加深入TLS API.

有没有人经历过类似的事情?我可以在我的级别实施任何解决方法吗?

编辑.根据要求,这里是分析调用跟踪,它生成了很多这些byte []:

.java.io.ByteArrayOutputStream.<init>(int)
..com.sun.net.ssl.internal.ssl.OutputRecord.<init>(byte, int)
...com.sun.net.ssl.internal.ssl.OutputRecord.<init>(byte)
....com.sun.net.ssl.internal.ssl.AppOutputStream.<init>(com.sun.net.ssl.internal.ssl.SSLSocketImpl)
.....com.sun.net.ssl.internal.ssl.SSLSocketImpl.init(com.sun.net.ssl.internal.ssl.SSLContextImpl, boolean)
......com.sun.net.ssl.internal.ssl.SSLSocketImpl.<init>(com.sun.net.ssl.internal.ssl.SSLContextImpl, java.net.Socket, String, int, boolean)
.......com.sun.net.ssl.internal.ssl.SSLSocketFactoryImpl.createSocket(java.net.Socket, String, int, boolean)
<my code>
Run Code Online (Sandbox Code Playgroud)

还有更多我能说的......这会很长.我会告诉你分析器给我的切入点:

....com.sun.net.ssl.internal.ssl.AppOutputStream.<init>(com.sun.net.ssl.internal.ssl.SSLSocketImpl)
....com.sun.net.ssl.internal.ssl.HandshakeOutStream.<init>(com.sun.net.ssl.internal.ssl.ProtocolVersion, com.sun.net.ssl.internal.ssl.ProtocolVersion, com.sun.net.ssl.internal.ssl.HandshakeHash, com.sun.net.ssl.internal.ssl.SSLSocketImpl)
....com.sun.net.ssl.internal.ssl.SSLSocketImpl.sendAlert(byte, byte)
..com.sun.net.ssl.internal.ssl.AppInputStream.<init>(com.sun.net.ssl.internal.ssl.SSLSocketImpl)
..com.sun.net.ssl.internal.ssl.SSLSocketImpl.performInitialHandshake()
..com.sun.net.ssl.internal.ssl.HandshakeInStream.<init>(com.sun.net.ssl.internal.ssl.HandshakeHash)
Run Code Online (Sandbox Code Playgroud)

jar*_*bjo 8

所有SSL连接都与SSL会话相关联,可以在不同的TCP连接之间重复使用,以便在建立实际TCP连接后协商临时加密密钥时减少握手开销.可能是您的客户端以某种方式强制创建新会话,并且由于Java 6的默认配置似乎是在一小时内缓存无限数量的会话,因此您可能很容易遇到内存问题.

您可以使用getSession().getSessionContext()从服务器套接字获取SSLSessionContext,并使用setSessionTime用setSessionCacheSize和timeout(以秒为单位)设置缓存大小,从而为服务器套接字操作这些设置.我原以为可以通过系统属性更改默认配置,但我无法找到任何相关文档.也许你可以通过谷歌搜索比我更长的时间找到自己的东西.


您确定要在正确的会话上下文中设置限制吗?我错误地认为可以从服务器套接字访问上下文.在创建服务器套接字之前,必须通过SSLContext进行设置:

SSLContext sslContext = SSLContext.getDefault();
sslContext.getServerSessionContext().setSessionCacheSize(1000);
SSLServerSocket ss = (SSLServerSocket)
     sslContext.getServerSocketFactory().createServerSocket(<port>);
Run Code Online (Sandbox Code Playgroud)

没有这个限制,很容易重现你的内存"泄漏",因为每个缓存的SSL会话接口使用大约7-800字节的堆内存.由于会话数限制,我的服务器现在已经在压力下运行了大约15分钟,并且仍然只使用3-4 MB的堆内存.

  • 86400sec是默认超时(即24h),您可以设置默认缓存大小:w /`-Djavax.net.ssl.sessionCacheSize = xxx`属性 (2认同)

DKS*_*ore 4

你看到连接关闭了吗?很可能这仍然以某种方式开放。1Mb 是一些额外线程的信号。但是,我不确定到底是什么原因。