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

Java:RMI目标对象的垃圾收集?,java,garbage-collection,rmi,Java,Garbage Collection,Rmi,当我用RMI弄脏我的双手时,我得到了一个java.RMI.NoSuchObjectException异常,这让我想到了这个问题:但我的问题不同 我在main方法中创建impl对象,因此在主线程中创建impl对象。如果我这样做: FooImpl fi = new FooImpl(); foo = (Foo) UnicastRemoteObject.exportObject(fi, 0); foo = (Foo) UnicastRemoteObject.exportObject(new FooIm

当我用RMI弄脏我的双手时,我得到了一个
java.RMI.NoSuchObjectException
异常,这让我想到了这个问题:但我的问题不同

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

FooImpl fi = new FooImpl();
foo = (Foo) UnicastRemoteObject.exportObject(fi, 0);
foo = (Foo) UnicastRemoteObject.exportObject(new FooImpl(), 0);
事情进展顺利

如果我这样做:

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
上调用一个方法

编辑2:如果我使用

Hello stub=(Hello)UnicastRemoteObject.exportObject(新服务器(),0)


首先绑定
foo
,然后绑定
hello
,然后在我尝试访问
hello
时引发相同的异常,因为现在收集的是服务器实例。真奇怪

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

在这些情况下更常见的问题是注册表本身,当由
LocateRegistry.createRegistry()
创建时,您没有这样做。如果是,创建的注册表本身也可以是GC'd:您必须将
注册表
引用保存在静态变量中。这样它就不会被GC'd,它将阻止存根
foo
被GC'd,存根将保持
FooImpl
不被DGC'd,从而被GC'd


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

一些其他信息:我发现调用“UnicastRemoteObject.exportObject()”会触发完整的gc。知道为什么/怎么做吗?我试图查找rmi源代码,但找不到它。我看到它通过Eclipse和命令行一致地发生。如果这是巧合的话,那就是非常一致的