2008-10-22 25 views
1

我的啓用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; 
    } 
    . 
    . 
    . 
} 
+0

好的解決辦法;你應該輸入它作爲答案,以便我可以投票! – erickson 2008-10-29 18:07:34

+0

爲什麼你更喜歡它到MySocketFactory?你的項目有什麼優勢? – 2008-11-06 12:06:41

回答

0
public class MySocketFactorySettingKeepAlive ... { 
    // overwrite createSocket methods, call super.createSocket, add keepAlive 
} 

Socket.setSocketImplFactory(youFactoryDemandingKeepAlive); 

,然後只用RMI。

如果我沒記錯的話,訣竅就是在系統打開第一個套接字之前設置工廠 - Java不允許覆蓋工廠;在最壞的情況下,使用反射來覆蓋它:)))(開玩笑;將是一個黑客)

此外,您可能需要允許在SecurityManager中的特定操作。