本文介绍了Java:RMI目标对象的垃圾回收?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

在使用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目标对象的垃圾回收?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持!

08-20 02:43