RMI注册表生命周期,GC等

时间:2011-02-03 12:42:01

标签: java garbage-collection rmi

在查看了Sun RMI教程后,我一直在进行内部Java RMI教程练习,而我只是有点了解正在发生的事情。有一些事情对我来说似乎很奇怪,我想知道在我对教程提出反馈之前究竟发生了什么。

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

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

首先,我注意到了:

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

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

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

我想了解一下有关exportObject实际工作方式的一些信息。(我想这与前一点有关 - 为什么有一个对象被删除会阻止程序结束?)

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

1 个答案:

答案 0 :(得分:0)

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

所以你有效地让另一个Thread监听这个ServerSocket,这会阻止你的应用程序退出(当没有非deamon线程运行时,Java VM退出)。

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