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

标签 java garbage-collection rmi

在尝试使用 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 上调用了一个方法。

EDIT2:如果我使用

Hello stub = (Hello) UnicastRemoteObject.exportObject(new Server(), 0);

并首先绑定(bind) foo,然后绑定(bind) hello,然后当我尝试访问 hello 时会抛出相同的异常,因为现在它是 Server 实例收集起来。真是奇怪的东西!

最佳答案

这两种方法都可能失败。它们在变量作用域方面没有真正的区别。

在这些情况下更常见的问题是注册表本身,当由 LocateRegistry.createRegistry() 创建时,您并没有这样做。如果是,则创建的注册表本身也可以被 GC:您必须将 Registry 引用保存在静态变量中。然后它将不会被 GC,并且它将阻止 stub foo 被 GC,并且 stub 将阻止 FooImpl 被 DGC,并且因此 GC。

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

关于Java:RMI 目标对象的垃圾回收?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/12746652/

相关文章:

java - 向 java.util.Calendar 添加真实的天数(不是一年中的天数)

c# - GC.Collect() 和 GC.Collect(GC.MaxGeneration) 有什么区别?

Java 线程垃圾是否收集

c# - 如何在程序中逐位执行除法?

java - 以编程方式生成 LinearLayout

ios - IOS 5 SDK 中的 Objective C 2.0 垃圾收集器 VS 自动引用计数器

java - Ant执行任意程序并在junit任务结束时终止

java - RMI 注册表远程异常错误

java - 如何将数据从一个java程序发送到另一个java程序

java - IntelliJ Git 集成插件 -> "New Branch"将大写 F 放入 "feature/abc"