我有一个服务器组件,我正试图对它进行负载测试。所有到服务器的连接都使用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)发布于 2009-10-26 17:11:58
你有没有看过连接很近。最有可能的是,它仍然以某种方式打开。1Mb是一些额外线程的信号。然而,我不确定到底是什么原因。
发布于 2009-10-26 17:09:22
所有SSL连接都与SSL会话相关联,在建立实际TCP连接之后协商临时加密密钥时,可以在不同的TCP连接之间重复使用SSL会话,以减少握手开销。这可能是因为您的客户端以某种方式强制创建了一个新会话,并且由于Java 6的默认配置似乎是缓存一个小时的无限数量的会话,因此您可能很容易遇到内存问题。
您可以使用getSession().getSessionContext()从服务器套接字获取SSLSessionContext,并使用setSessionCacheSize设置缓存大小,使用setSessionTimeout设置超时(以秒为单位),从而操作服务器套接字的这些设置。我本以为可以通过系统属性更改默认配置,但我找不到任何有关这方面的文档。也许你可以通过搜索比我更长一点的时间自己找到一些东西。
您确定在正确的会话上下文上设置了限制吗?我搞错了可以从服务器套接字访问的上下文。您必须在创建服务器套接字之前通过SSLContext进行设置:
SSLContext sslContext = SSLContext.getDefault();
sslContext.getServerSessionContext().setSessionCacheSize(1000);
SSLServerSocket ss = (SSLServerSocket)
sslContext.getServerSocketFactory().createServerSocket(<port>);如果没有这个限制,就很容易重现内存“泄漏”,因为每个缓存的SSL会话都需要使用大约7-800字节的堆内存。有了会话计数限制,我的服务器现在已经在压力下运行了大约15分钟,并且仍然只使用了3-4MB的堆内存。
发布于 2009-10-26 17:59:33
1MB是创建线程所需的内存,无论是否额外。
这个类或包的bug列表中是否有任何条目?第一步是检查它。
第二步是假设问题出在您的代码中,而不是Sun的东西上。这更有可能,原因很简单,因为Java JDK中的一个常用类已经被世界各地的用户所使用。如果有一个错误,它现在应该已经曝光了。
这并不是说JDK代码没有bug,只是您应该首先怀疑您的代码。
找个剖析器测量一下。别猜了。
https://stackoverflow.com/questions/1623676
复制相似问题