虽然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实例。真的很奇怪!
答案 0 :(得分:3)
这两种方法都可能失败。在变量范围方面,它们之间没有真正的区别。
在这些情况下更常见的问题是注册表本身,由LocateRegistry.createRegistry()
创建时,您没有这样做。如果是,创建的注册表本身也可以是GC:您必须将Registry
引用保留在静态变量中。然后它将不会是GC,它将阻止存根foo
被GC,并且存根将使FooImpl
保持DGC并因此GC。< / p>
在您的情况下,最好将远程对象引用(服务器,而不是存根)保留在静态变量中。