我的启用RMI的应用程序似乎在泄露套接字。我有一个Java应用程序通过RMI提供服务。它使用在Linux上运行的Java SE 1.6 RMI实现。我观察到的问题是,如果客户端使用注册表获取对Remote对象的引用,然后突然断开连接(断电,拔掉电缆等),服务器将保持套接字打开。我希望在客户的租约到期后清理RMI实现,但这不会发生。在服务器上,当租约到期时调用Remote对象的unreferenced()
方法,但套接字在netstat中始终以“ESTABLISHED”状态无限期地可见。租约到期后Java RMI未关闭套接字
由于我们无法强制客户端进入任何特定行为,因此在几天后,我们在Linux发行版中达到默认限制1024(对于打开文件描述符),导致服务器无法打开任何新套接字或文件。我想过TCP keepalive,但是由于RMI正在抽象掉网络层,所以在建立连接后,我无法访问实际的服务器套接字。
有没有什么办法强制RMI层清理与过期租约的客户端连接绑定的套接字?
更新:我使用的解决方案与所选答案类似,但使用了不同的方法。我使用了一个自定义的套接字工厂,然后将包含createServerSocket()返回的ServerSocket实例包装在一个透明的包装器中,该包装器通过了所有方法,accept()除外。在accpet方法中,keepalives在返回套接字之前启用。
public class KeepaliveSocketWrapper extends ServerSocket
{
private ServerSocket _delegate = null;
public KeepaliveSocketWrapper(ServerSocket delegate)
{
this._delegate = delegate;
}
public Socket accept() throws IOException
{
Socket s = _delegate.accept();
s.setKeepAlive(true);
return s;
}
.
.
.
}
好的解决办法;你应该输入它作为答案,以便我可以投票! – erickson 2008-10-29 18:07:34
为什么你更喜欢它到MySocketFactory?你的项目有什么优势? – 2008-11-06 12:06:41