我有一个服务器组件,我正在尝试加载测试。与服务器的所有连接都使用TLS 1.0。我有一个简单的测试程序,基本上可以在我想要的多个线程上执行此操作:
Full TLS handshake to the server
send a request
read reply
close connection
repeat ad nauseam
我的虚拟机如下:
Java(TM) SE Runtime Environment (build 1.6.0_16-b01)
Java HotSpot(TM) Server VM (build 14.2-b01, mixed mode)
我有内存泄漏。当我对服务器进行大量测试时,我的内存占用量每秒增加大约1兆字节,这使得它在OutOfMemoryException
15-20分钟后就会阻塞。
我在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>
还有很多我可以放的......这会很长。我会告诉你分析器给我的切入点:
....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)
答案 0 :(得分: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>);
没有这个限制,很容易重现你的内存“泄漏”,因为每个缓存的SSL会话接口使用大约7-800字节的堆内存。由于会话数量限制,我的服务器现在已经在压力下运行了大约15分钟,并且仍然只使用3-4 MB的堆内存。
答案 1 :(得分:4)
你看到连接关闭了吗?很可能这仍然以某种方式开放。 1Mb是一些额外的线程。但是,我不确定究竟是什么原因。
答案 2 :(得分:1)
1MB是创建线程所需的内存,额外与否。
该类或包的错误列表中是否有任何条目?第一步是检查它。
第二步是假设问题出在你的代码中,而不是Sun的东西。它更有可能,仅仅是因为Java JDK中常用的类已经被全世界的用户所击败。如果出现错误,那么它现在就会被曝光。
这并不是说JDK代码没有错误,只是你应该首先怀疑你的代码。
获取分析器并进行测量。不要猜。
答案 3 :(得分:0)
你在运行什么硬件?你可以做一个netstat并验证你的连接状态吗?
我已经加载了测试Tomcat,并且在Solaris上运行了1 GB的堆,并且运行了几个小时,并且没有遇到500个新的SSL请求/秒。此外,您可能希望监视容器中运行的线程数。