Java:RMI目标对象的垃圾收集?

时间:2012-10-05 12:51:00

标签: java garbage-collection rmi

虽然RMI弄得很脏,但我得到了java.rmi.NoSuchObjectException例外,这让我想到了这个问题:java.rmi.NoSuchObjectException: no such object in table ,但我的问题不同

我正在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,然后在Hello stub = (Hello) UnicastRemoteObject.exportObject(new Server(), 0);上调用方法。

EDIT2:如果我使用

foo

并首先绑定hello,然后绑定hello,然后当我尝试访问{{1}}时抛出相同的异常,因为现在它正在收集的Server实例。真的很奇怪!

1 个答案:

答案 0 :(得分:3)

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

在这些情况下更常见的问题是注册表本身,由LocateRegistry.createRegistry()创建时,您没有这样做。如果是,创建的注册表本身也可以是GC:您必须将Registry引用保留在静态变量中。然后它将不会是GC,它将阻止存根foo被GC,并且存根将使FooImpl保持DGC并因此GC。< / p>

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