Java RMI返回对远程对象的引用而不绑定

Java RMI返回对远程对象的引用而不绑定,java,rmi,remoteobject,rmiregistry,Java,Rmi,Remoteobject,Rmiregistry,我有一个服务器和一个客户端通过RMI进行通信。他们的目标是共享一个简单的对象,一起工作,然后模拟服务器断开连接 服务器的名称已绑定到注册表。客户端使用RMI注册表获取对服务器的远程引用。然后它使用此引用调用一个方法,该方法返回对它们将共享的对象的引用。通过该共享对象进行进一步的通信 共享对象是UnicastRemoteObject,服务器拥有它的实现,并有一个方法返回对客户端的引用 客户端知道共享对象的接口,从服务器获取远程引用,然后对其进行操作。请注意,服务器应返回远程引用,而不是序列化副本

我有一个服务器和一个客户端通过RMI进行通信。他们的目标是共享一个简单的对象,一起工作,然后模拟服务器断开连接

服务器的名称已绑定到注册表。客户端使用RMI注册表获取对服务器的远程引用。然后它使用此引用调用一个方法,该方法返回对它们将共享的对象的引用。通过该共享对象进行进一步的通信

共享对象是UnicastRemoteObject,服务器拥有它的实现,并有一个方法返回对客户端的引用

客户端知道共享对象的接口,从服务器获取远程引用,然后对其进行操作。请注意,服务器应返回远程引用,而不是序列化副本

这是共享对象接口

public interface CInterface extends Remote {
    boolean testMethod() throws RemoteException;
}
这就是它的实现

public class CImpl implements CInterface {
    @Override
    public boolean testMethod() throws RemoteException {
        return false;
    }
}
这是服务器在客户端调用远程引用时应返回远程引用的方法

public CInterface exportRefToC() throws RemoteException {
    return new CImpl();
}
如果我从客户端调用它,它会给我这个异常

java.rmi.UnmarshalException:错误解组返回;嵌套 异常为:java.io.WriteAbortedException:写入中止; java.io.NotSerializableException:sandbox.CImpl

如果我这样写的话,我可以让这个方法工作并返回一个远程引用

public CInterface exportRefToC() throws RemoteException {
    refToC = new CImpl();
    return (CInterface) UnicastRemoteObject.exportObject(refToC, 1099);
}
我不明白的是为什么我需要再次检查注册表,尽管没有显式地绑定名称,只是为了返回远程引用。客户机在使用RMI注册表之前获得了对服务器的引用,因此引导已经完成。现在,为什么服务器不能在不知道rmiregistry(1099)的端口的情况下返回对客户端的引用呢

另外一个问题是,如果服务器想要使它与客户端共享的对象不可用(以模拟断开连接),有没有比这更好的方法

UnicastRemoteObject.unexportObject(refToC, true);
编辑:如果我在共享对象的实现中扩展UnicastRemoteObject,则该方法的第一个版本可以工作,但是,unexport不工作并返回此异常

java.rmi.ServerException:服务器线程中发生RemoteException; 嵌套异常为:java.rmi.NoSuchObjectException:对象不是 出口

EDIT2:再次选中,它确实有效,只需在返回引用之前保存引用即可

public CInterface exportRefToC() throws RemoteException {
    refToC = new CImpl();
    return refToC;
}
共享对象是一个
UnicastRemoteObject

不,不是。再看看:

public class CImpl implements CInterface
添加
扩展UnicastRemoteObject
,并提供适当的构造函数,您的问题就会消失

您不需要调用
exportObject(),
,也不需要对注册表进行第二次绑定

你的最后一个问题是一个错误。它应该是
unexportObject(),
,这是使对象不可用的正确方法