我已经遵循了一堆关于这个RMI业务的教程,以了解如何正确地做到这一点。Oracle的教程使用了SecurityManager
,而大多数其他教程则没有使用。有些扩展了UnicastRemoteObject
,而另一些扩展了exportObject
。有些人从外部运行RMIRegistry
和getRegistry
,而其他人则运行createRegistry
。
现在,我想从我面前的这些选项中挑选出来对我来说是有益的,所以我这样做了:
首先,我选择了安全,因为为什么不呢?
其次,我不喜欢扩展UnicastRemoteObject
,因为我的对象并不完全是远程的,只是有一些远程方法。例如,在它的构造函数中有一个throws RemoteException
子句对我来说就是不正确的。
最后,我不想从外部运行注册表,因为我并没有真正运行服务器,它只是一个应用程序。此外,我不想有两个/三个单独的地方设置注册表的 * 端口 *。
下面是我的服务器代码,(希望如此)做我所描述的事情:
package server;
import interf.TicTacToeBoard;
import java.rmi.AlreadyBoundException;
import java.rmi.RemoteException;
import java.rmi.registry.LocateRegistry;
import java.rmi.registry.Registry;
import java.rmi.server.UnicastRemoteObject;
public class TicTacToeServer
{
private static Registry registry;
public static void main(String[] args)
throws RemoteException, AlreadyBoundException
{
System.out.println("Server is up!");
System.setProperty("java.security.policy", "file:/<policy_file_path>");
if (System.getSecurityManager() == null)
System.setSecurityManager(new SecurityManager());
TicTacToeBoardImpl arena = new TicTacToeBoardImpl();
TicTacToeBoard stub =
(TicTacToeBoard) UnicastRemoteObject.exportObject(arena, 0);
registry = LocateRegistry.createRegistry(TicTacToeBoard.RMI_PORT);
registry.bind(TicTacToeBoard.RMI_NAME, stub);
System.out.println("Waiting for connections.");
}
}
这东西还不完整但就能够为远程对象提供服务而言,它应该是。但是,在用"Waiting for connections."
打印那一行之后,应用程序只是默默地终止。
我对此的唯一解释是,应用程序被垃圾收集。
在Oracle的示例中,它不会得到垃圾收集,因为在那里,RMIRegistry作为一个独立于服务器应用程序的应用程序运行,并且RMIRegistry应用程序保存对驻留在服务器应用程序内的对象的引用。
当我的实现extends UnicastRemoteObject
时,它不会被垃圾收集,因为...我不知道我所知道的是,应用程序然后继续运行。
如果我在任何阶段错了,请纠正我。最重要的是,我的问题是,我有什么选择,不涉及运行一个RMIRegistry作为一个单独的进程,使我的实现扩展UnicastRemoteObject
?
2条答案
按热度按时间xxe27gdn1#
这不应该发生。1两个远程对象的存在应该保持端口侦听线程的运行,静态变量应该保持注册表对象的存在。尝试将实现和存根字段设置为静态字段,就像注册表一样。
我是为了安全才去的,为什么不呢?
但是为什么呢?这只是一个麻烦,除非你要运行不受信任的代码,或者在别人的计算机上运行。
1、事实上,这并没有发生在我身上。它一直在跑。您确定您的
Registry
引用真的是static
吗?pieyvz9o2#
万一我忘了...
extends UnicastRemoteObject
在我的类定义中。