문제

RMI 활성화 응용 프로그램은 소켓이 누출되는 것 같습니다. RMI에 대한 서비스를 제공하는 Java 응용 프로그램이 있습니다. Linux에서 실행되는 Java SE 1.6 RMI 구현을 사용하고 있습니다. 내가 관찰하는 문제는 클라이언트가 레지스트리를 사용하여 원격 객체에 대한 참조를 얻은 다음 연결이 갑자기 절단되면 (전력 손실, 케이블이 플러그되지 않은 등) 서버가 소켓을 열어 두는 것입니다. 고객의 임대가 만료 된 후 RMI 구현이 정리 될 것으로 예상되지만 이는 일어나지 않습니다. 서버에서 내 원격 객체의 것입니다 unreferenced() 임대가 만료되면 방법이 호출되지만 소켓은 "확립 된"상태에서 Netstat에서 표시되지 않습니다.

우리는 클라이언트를 특정 동작으로 강요 할 수 없기 때문에 며칠 후에 Linux 배포판의 1024를 열기 위해 서버가 새 소켓이나 파일을 열 수 없게됩니다. 나는 TCP Keepalives에 대해 생각했지만 RMI가 네트워크 계층을 추상화하고 있으므로 연결이 설정된 후 실제 서버 소켓에 액세스 할 수 없습니다.

RMI 계층을 만료 된 임대로 클라이언트 연결과 연결된 정리 소켓을 강제로 강제 할 수있는 방법이 있습니까?

업데이트: 내가 사용한 솔루션은 선택한 답변과 유사하지만 다른 접근법을 사용합니다. 사용자 정의 소켓 공장을 사용한 다음 CreateServersocket ()에 의해 반환 된 서버 소켓 인스턴스를 투명한 래퍼에서 셉션 ()을 제외하고 모든 메소드를 통과 시켰습니다. 셀프 방법에서는 소켓이 반환되기 전에 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;
    }
    .
    .
    .
}
도움이 되었습니까?

해결책

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

Socket.setSocketImplFactory(youFactoryDemandingKeepAlive);

그런 다음 RMI를 사용하십시오.

제가 옳은 것을 기억한다면, 시스템이 첫 번째 소켓을 열기 전에 공장을 설정하는 것입니다. 최악의 경우, 반사를 사용하여 그것을 덮어 씁니다 :))) (농담; 해킹이 될 것입니다)

또한 SecurityManager에서 특정 작업을 허용해야 할 수도 있습니다.

라이센스 : CC-BY-SA ~와 함께 속성
제휴하지 않습니다 StackOverflow
scroll top