【发布时间】: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