【问题标题】:RMI Registry lifetime, GC etcRMI Registry 生命周期、GC 等
【发布时间】:2011-06-20 15:40:36
【问题描述】:

在查看了 Sun RMI 教程之后,我一直在做一个内部 Java RMI 教程练习,我只是有点了解发生了什么。有几件事对我来说似乎很奇怪,在我就教程提供反馈之前,我想知道真正发生了什么。

本教程让我编写以下组件:

  • 一个接口,比如 RemoteInterface,带有我们希望远程访问的方法。
  • 一个类,比如 RemoteServer,实现 RemoteInterface,在其构造函数中:
    • 通过调用LocateRegistry.createRegistry(PORTNO) 创建一个注册表对象
    • 通过调用UnicastRemoteObject.exportObject(this, PORTNO) 并转换结果来创建一个存根RemoteInterface 对象。
    • 使用registry.rebind(BINDNAME, stub) 将存根绑定到注册表
  • 一个类,比如 ServerDemo,它有一个 main 方法,它只创建一个 RemoteServer 的实例。
  • 使用 BINDNAME 调用服务器的客户端类,一切正常。

首先,我注意到:

  • main 方法完成后服务器继续运行。我必须明确终止它。在我看来,它应该只是创建一个对象然后完成,但程序不会终止,客户端仍然可以连接。
  • 如果我在 RemoteServer 构造函数中调用 registry.unbind(BINDNAME),客户端会停止工作,但服务器仍然不会终止。
  • 如果我在 RemoteServer 构造函数中调用UnicastRemoteObject.unexportObject(this, true);,服务器会立即终止。

我想知道为什么会这样 - 虽然如果不是这样,服务器将毫无用处,因为它会立即终止。 (在我的反馈中,我将建议为 ServerDemo 调用 RemoteServer 绑定和取消绑定方法,而不是在构造函数中进行所有绑定,从不取消绑定,并且由于某种原因依赖服务器继续运行 - 但首先我'想知道为什么会这样。)

其次,我注意到我可以调用UnicastRemoteObject.exportObject(this, PORTNO) 之前调用LocateRegistry.createRegistry(PORTNO) 并且一切仍然有效。我认为必须先设置注册表,然后才能导出到它,但显然它不像我想的那样工作。

我想要一些关于 exportObject 实际工作原理的信息。(我想这与前一点有关 - 为什么将对象 exprted 阻止程序结束?)

另外,如果我在一种方法中导出和绑定存根,准备在另一种方法中取消导出和解除绑定,我想知道我是否需要明确保留对存根的引用介于两者之间。 (解除绑定只需要 BINDNAME。)我的一位同事报告了 GC 问题,虽然我自己没有注意到任何问题,但我不能排除它们,因为我真的不明白发生了什么。

【问题讨论】:

    标签: java garbage-collection rmi


    【解决方案1】:

    默认情况下,RMI 通过为每个导出的对象运行一个 TCP 服务器来工作。该服务器侦听您提供的端口并等待是否有客户端连接到那里,然后执行被调用的方法。

    因此,您实际上有另一个线程在此 ServerSocket 上进行侦听,这会阻止您的应用程序退出(当没有运行非守护线程时,Java VM 会退出)。

    实际上,这与您的注册表完全没有关系,在您的情况下似乎根本没有使用。

    【讨论】:

    • 注册表在客户端中使用——它调用LocateRegistry.getRegistry(HOSTNAME, PORTNO),然后使用该注册表查找导出的对象。但是我注意到我可以不使用UnicastRemoteObject.exportObject 调用并绑定RemoteServer 对象而不是存根,除了在客户端而不是服务器上出现一些System.out 输出之外,一切都可以工作......现在我更困惑:/
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2021-05-23
    • 1970-01-01
    • 1970-01-01
    • 2013-04-06
    • 1970-01-01
    • 2014-09-10
    • 1970-01-01
    相关资源
    最近更新 更多