1

在弄脏 RMI 时,我遇到了一个java.rmi.NoSuchObjectException异常,这导致我提出了这个问题:java.rmi.NoSuchObjectException: no such object in table but my question is different

我在我的 main 方法中创建 impl 对象,因此在主线程中。如果我这样做:

FooImpl fi = new FooImpl();
foo = (Foo) UnicastRemoteObject.exportObject(fi, 0);

一切正常。

如果我这样做:

foo = (Foo) UnicastRemoteObject.exportObject(new FooImpl(), 0);

我看到收集了 FooImpl 实例,然后我得到了上述异常。

foo是我在 main 中初始化的静态引用;另一个远程对象foo从其方法之一返回。因此,客户端首先获取该远程对象,然后从中获取foo,然后调用一个方法foo,这就是我得到上述异常的时候。那么为什么会这样呢?

编辑:这是我的主要方法

public static void main(String[] args) throws RemoteException, AlreadyBoundException 
{

    Server server = new Server();
    Hello stub = (Hello) UnicastRemoteObject.exportObject(server, 0);

    FooImpl fi = new FooImpl();
    foo = (Foo) UnicastRemoteObject.exportObject(fi, 0);

    Registry registry = LocateRegistry.getRegistry();
    registry.bind("Hello", stub);       
    System.out.println("Server ready!");        
}

在客户端,我正在获取hello并调用一个方法,它给了我foo,然后调用一个方法foo

EDIT2:如果我使用

Hello stub = (Hello) UnicastRemoteObject.exportObject(new Server(), 0);

foo然后先绑定hello,然后当我尝试访问时抛出相同的异常,hello因为现在它是正在收集的服务器实例。真是奇怪的东西!

4

1 回答 1

3

这两种方法都可能失败。在变量范围方面,它们之间没有真正的区别。

在这些情况下更常见的问题是注册表本身,当您创建时LocateRegistry.createRegistry(),您没有这样做。如果你是,创建的注册表本身也可以被 GC 处理:你必须将Registry引用保存在静态变量中。然后它不会被 GC'd,它会阻止 stubfoo被 GC'd,并且 stub 将阻止FooImplDGC'd 并因此 GC'd。

在您的情况下,您最好将远程对象引用(服务器,而不是存根)保存在静态变量中。

于 2012-10-05T22:35:19.657 回答