Java RMI - UnicastRemoteObject:UnicastRemoteObject.exportObject()和扩展UnicastRemoteObject有什么区别?

时间:2010-02-03 19:48:22

标签: java interface export rmi

我正在准备考试,我有一个问题,希望有人能回答我。

这是关于RMI和远程对象。我想知道为什么这两个实现之间存在很大差异。一个是扩展UnicastRemoteObject而另一个是将对象导出为UnicastRemoteObject。

我真的没有区别

接口:

public interface EchoI extends Remote {
   public String echo() throws RemoteException
}

这是服务器代码(版本1):

public class EchoImpl extends UnicastRemoteObject implements EchoI {
    public EchoImpl {
        super();
    }

    public static void main (String[] args) {
        try {
            LocateRegistry.createRegistry(Registry.REGISTRY_PORT);
            StoreHouse storehouseImpl = new StorehouseImpl();
            Naming.rebind("//localhost/StoreHouse.SERVICE_NAME", storehouseImpl);
            System.out.println("Server ready");
        } catch (RemoteException e) {
            e.printStackTrace();
        } catch (MalformedURLException e) {
            e.printStackTrace();
        }
    }

    public String echo() {
        return "echo";
    }
}

这将是版本2:

public class EchoImpl implements EchoI {
    public static void main (String[] args) {
        EchoI echoService = new EchoImpl();
        EchoI stub = (EchoI) UnicastRemoteObject.exportObject(echoService, 0);
        Registry registry = LocateRegistry.getRegistry();
        registry.bind("echoService", stub);
        ...
    }
}

我的问题是:这两者之间有什么区别?

在第一个版本中,显式创建了注册表,而且远程对象是在重新绑定中创建的吗?

我真的很好奇,为什么在第一个我需要自己创建注册表但不需要显式导出对象而只需使用Naming重新绑定它。该对象之前是否已绑定到注册表,或者我可以使用bind吗?如果对象之前没有绑定并重新绑定,那么会发生什么?

在第二个版本中,注册表似乎已经创建。 为什么绑定命名与直接绑定到注册表相同?

这就是我的想法:

  • 第一个类direclty实现了UnicastRemoteObject接口,这意味着在运行时创建了注册表,并且该对象会自动导出到RMI注册表。
  • 由于对象已绑定到注册表,因此必须重新绑定而不是正常绑定。
  • 后者明确地做了所有这些。

4 个答案:

答案 0 :(得分:19)

这里有两个问题。

  1. 您可以延长UnicastRemoteObject或致电UnicastRemoteObject.exportObject().您所做的事由您决定。第一个是简单和自动的;第二个意味着你可以扩展另一个类。

  2. 您可以使用外部RMI注册表,也可以在服务器JVM中自行创建。你做的再取决于你,两种方式都有优势。

    这两个问题没有互动。

  3. 如果你extend UnicastRemoteObject,你也可以获得hashCode()equals()方法的'远程语义'的好处,这样所有存根看起来都与远程对象相同导出它们,但这在客户端没有实际用途,实际上只是支持RMI实现本身。

答案 1 :(得分:4)

java.rmi.server.UnicastRemoteObject用于通过Java远程方法协议(JRMP)导出远程对象并获取与远程对象通信的存根。

对于下面的构造函数和静态exportObject方法,将获取正在导出的远程对象的存根...

你应该遵循Javadoc

答案 2 :(得分:0)

您可以在需要扩展任何其他类的场景中调用UnicastRemoteObject.exportObject()而不是扩展UnicastRemoteObject。我认为整体效果是一样的。

See this

答案 3 :(得分:0)

首先,绑定&使用Naming类和Registry类重新绑定远程对象与类是否正在扩展UnicastRemoteObject的方案无关。有关差异,请参阅here

其次,扩展UnicastRemoteObject的类之间的区别在于,如果该类型的对象用作存根,那么您不需要再调用UnicastRemoteObject.exportObject来获取存根用于绑定注册表。在您的版本1中,StorehouseImpl必须扩展UnicastRemoteObject,事实上,EchoImpl不需要为您的版本1扩展UnicastRemoteObject没有EchoImpl的实例被注册为注册表的远程对象。

第三,你提到如果事先没有rebind执行bind就会发生什么。正如javadoc here中所解释的那样,如果没有插入密钥名称,它的行为方式与第一次执行bind的方式相同。