问题描述
在使用RMI弄到我的手时,我得到了一个 java.rmi.NoSuchObjectException
异常,这引发了这个问题: 但我的问题不同 em>。
我在主方法中创建impl对象,因此在主线程中创建。如果我这样做:
FooImpl fi = new FooImpl();
foo =(Foo)UnicastRemoteObject.exportObject(fi,0);
事情正常。
如果我这样做:
foo =(Foo)UnicastRemoteObject .exportObject(new FooImpl(),0);
我看到FooImpl实例被收集,然后我得到了上述异常。
foo
是一个静态引用,我在main中初始化;另一个远程对象从它的一个方法中返回 foo
。因此,客户端首先获取该远程对象,然后从中获取 foo
,然后调用 foo
上的方法,这就是当我得到如上所述的例外。那么为什么会发生这种情况?
编辑:这是我的主要方法
<$ c
$ b $服务器服务器=新的服务器(); $ c $ public static void main(String [] args)throws RemoteException,AlreadyBoundException
Hello stub =(Hello)UnicastRemoteObject.exportObject(server,0);
FooImpl fi = new FooImpl();
foo =(Foo)UnicastRemoteObject.exportObject(fi,0);
注册表注册表= LocateRegistry.getRegistry();
registry.bind(Hello,stub);
System.out.println(Server ready!);
$ / code>
在客户端中,我得到了 hello
并调用一个方法,它给了我
foo
,然后在 foo
上调用一个方法。
EDIT2:如果我使用
Hello stub =(Hello)UnicastRemoteObject.exportObject new Server(),0);
并绑定 foo
code> hello ,则当我尝试访问 hello
时会抛出相同的异常,因为现在它正在收集服务器实例。真是奇怪的东西!
两种方法都有可能失败。他们之间在变量范围方面没有实质区别。
在这些情况下更常见的问题是注册表本身,当由 LocateRegistry .createRegistry()
,你没有做。如果是,创建的注册表本身也可以GC'd:您必须将注册表
引用保留在静态变量中。然后它不会被GC'd,它会阻止存根 foo
被GC'd,并且存根将保持 FooImpl
由DGC'd因此GC'd。
在你的情况下,你最好保留远程对象引用(服务器,而不是stub) )在静态变量中。
While getting my hands dirty with RMI, I got a java.rmi.NoSuchObjectException
exception, which led me to this question: java.rmi.NoSuchObjectException: no such object in table but my question is different.
I'm creating the impl object in my main method and hence in the main thread. If I do this:
FooImpl fi = new FooImpl();
foo = (Foo) UnicastRemoteObject.exportObject(fi, 0);
things work fine.
If I do this:
foo = (Foo) UnicastRemoteObject.exportObject(new FooImpl(), 0);
I see that FooImpl instance is collected and then I get the aforementioned exception.
foo
is a static reference that I'm initializng in main; and another remote object returns foo
from one of its methods. So a client gets that remote object first, then gets foo
from it, and then calls a method on foo
and that's when I get the exception as explained above. So why is it happening this way?
EDIT: here's my main method
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!");
}
In client, I'm getting hello
and calling a method on it which gives me foo
and then calling a method on foo
.
EDIT2: If I use
Hello stub = (Hello) UnicastRemoteObject.exportObject(new Server(), 0);
and bind foo
first and then hello
, then same exception is thrown when I try to access hello
because now it's Server instance which is getting collected. Really weird stuff!
Both approaches are liable to fail. There's no real difference between them in terms of variable scoping.
The problem more usually seen in these situations is the Registry itself, when created by LocateRegistry.createRegistry()
, which you aren't doing. If you were, the created Registry itself can be GC'd too: you must keep the Registry
reference in a static variable. Then it won't be GC'd, and it will prevent the stub foo
from being GC'd, and the stub will keep the FooImpl
from being DGC'd and therefore GC'd.
In your case you would be better off keeping the remote object references (servers, not stubs) in static variables.
这篇关于Java:RMI目标对象的垃圾回收?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持!