Java:RMI目标对象的垃圾收集?
当我用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
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和命令行一致地发生。如果这是巧合的话,那就是非常一致的