您的位置:寻梦网首页编程乐园JAVA 天地RMI 专辑>用分布式对象技术构造Java应用
用分布式对象技术构造Java应用
用Java,RMI和HORB 实现分布式对象环境

摘 要 本文原发表在十二月的日文JavaWorld 印刷版上,概括地介绍了分布式对象技术,点介绍了其中 的 两种具体技术:远程方法启用(RMI)和Hirano对象请求代理(HORB)。通过代码实例和图解,你自己便能判定哪种分布式对象技术最适合你。

直到最近,软件程 序用面向对象设计方法创建时,设计主要运行在单机的内存里。为了使软件适应网络 运用和保存在二级存贮里,除了面向对象方法以外,还需要其他的设计方法。人们开 发了面向网络的分布式对象技术来解决这个问题。同时,可以将对象直接存贮在二级 存贮里的面向对象数据库(ODBMS)技术诞生了。

这些技术都不是新 的,--支持ODBMS的开发工具在90年代早期便出现在市场上,然而这些产品不是价格太高,使用无名的语言,就是没有获得工程师行业的广泛认可。随着Java的出现,分 布式对象技术和ODBMS技术得到了进一步的发展,而且价格下降了,所以获得了工程师们的接受。根据最近软件的动向,这些技术得到越来越广泛的关注。

很明显,未来的软 件环境必须包括三项重要的技术:

1.“ 面向对象”

2.“ 网络”

3.“ 数据库”

这些环境可以用分布式对象技术和ODBMS来实现。本文的中心是基于Java 的分布式对象技术。

什么是分布式对象

简单说来,分布式对象技术允许在不同机器上的对象相互传递消息(Java方法调用)。为了便于理解什么是分布式对象,请看图1,一个网络卡拉OK模型的设计。正如你看到的,当一个远程操作在服务器中的Karaoke box 执行歌曲选择时,一个Music对象将被送到客户机。客户机通过发送“播放”消息启动音乐。以下定义一些术语:等同于Karaoke box 的对象称为“远程对象”,发送给客户机的Music对象称为“拷贝对象”,由客户机发往服务器上的Karaoke box对象的消息称为“远程消息”,我们将用这个模型实现一个分布式对象系统。

图1: 网络卡拉OK模型图

RMI和HORB概述

本文的中心是两项分布式对象技术:RMI(远程方法启用),它捆绑于JDK1.1的标准特征中,和HORB(Hirano对象请求代理),它由美国国家电子研究所(国际贸易和工业部)的Satoshi Hirano开发。本文的最后将介绍CORBA,它致力于成为工业标准的分布式对象系统。关于HORB的最新信息,可在以下URL中查到:http://ring.tel.go.jp/openlab/horb/。

分布式对象的应用(HORB与RMI)

我试图用这两项技术,HORB和RMI来构造一个分布式对象系统。理解这些技术最快的方法是通过获得实际的动手经验。

首先,我们将基于网络卡拉OK模型设计类。图2为一个类示图,它说明了基于内部类结构和类创建的实例之间的关系结构。

图2:网络卡拉OK模型的类示图

HORB介绍

这部分提供一个如何使用HORB的例子。与RMI相比,HORB允许以类似于常规面向对象编程的格式编码,列表1是HORB卡拉OK类的源代码(Karaoke.java)

列表1:Karaoke box类[HORB]

  class KaraokeBox{
    void hello(String s){
      System.out.println("Client Name " + s);
    }
  }

列表2是使用Karaoke box的客户机的源代码(Client.java)。首先调用KaraokeBox类的hello()方法。到此,程序不是分布式对象。对KaraokeBox类的hello()方法的调用也是本地调用。

列表2:使用Karaoke box的客户机的源代码[HORB]

  classClient{
    public static void main(String argv[]){
      String name = (argv.length == 1) ? argv[0] : "-";
      KaraokeBox  box = new KaraokeBox();
      box.hello(name);
    }
  }

现在我们将用一个小魔术将KaraokeBox转换成远程对象。首先对客户机源代码做修改。如列表3所示。这将告诉你在远程操作中如何使用KaraokeBox(Client.java)。由列表2中修改的部分用注释标注。在列表3中,创建了KaraokeBox_Proxy的实例,而不是KaraokeBox。那么什么时候创建最重要的KaraokeBox实例?答案是在创建KaraokeBox_Proxy实例时。

列表3:在远程操作中使用KaraokeBox(Client.java)[HORB]

  import horb.orb.*;  // Add
 
  class Client{
    public static void main(String argv[]){
      String name = (argv.length == 1) ? argv[0] : "-";
      KaraokeBox_Proxy box = new KaraokeBox_Proxy("horb://kinta");
             // Change (change host name)
      box.hello(name);
    }
  }

在下面的代码例子中,你将看到在RMI操作中如何使用KaraokeBox(Client.java)

列表4:在RMI操作中使用KaraokeBox(Client.java)[RMI]

  classClient{
    public static void main(String argv[]){
    String name = (argv.length == 1) ? argv[0] : "-";
    try{ // Change
      KaraokeBox box = (KaraokeBox)java.rmi.Naming.lookup("rmi://kinta/karaokebox1");
                   // Change
      box.hello(name);
    }   // Change
    catch(Exception e){e.printStackTrace();}  // Change
    }
  }

  图3 显示了Karaoke box的机制。

图3:Karaoke box的远程操作机制[HORB]

KaraokeBox_Proxy称为KaraokeBox的“代理对象”。KaraokeBox的实际实例位于服务器上(本例中的主机名为“kinta”)。客户机创建KaraokeBox_Proxy的实例作为代理对象。发送给KaraokeBox的消息先发给KaraokeBox_Proxy,消息通过KaraokeBox_Proxy和被称为Karaoke_Skeleton的机制转发给KaraokeBox实例,Karaoke_Skeleton位于服务器上,结果返回到客户机。所以远程对象操作才成为可能。

这是必要的源代码修改。HORB一个很好特点是远程对象KaraokeBox的源代码根本不用修改。

创建运行环境

HORB编译器会自动创建KaraokeBox_Proxy和Karaoke_Skeleton。与往常一样,Client.java用Java编程器编译。

1.> horbc KaraokeBox.java 创建

  • KaraokeBox.class
  • KaraokeBox_Proxy.class
  • KaraokeBox_Skeleton.class

2.> javac Client.java 创建

  • Client.class.

3. 将Client.class和KaraokeBox_Proxy.class拷贝到客户机,将KaraokeBox.class和KaraokeBox_Skeleton.class拷贝到服务器(HORB必须安装在客户机和服务器上)。

运行过程

1.在服务器上启动HORB精灵。

2.在客户机上以字符串“Junzo”作为参数启动Client.

3.结果"Client Name Junzo"显示在服务器上。

运行结果如图4所示

图4 :HORB 运 行 结 果

RMI介绍

本部分介绍如何使用RMI。首先,修改客户机的源代码,如列表4所示。修改的位置几乎与HORB的修改一样。从列表2的修改用注释标注。

在列表4中,使用了称为lookup()的RMI方法代替调用new创建KaraokeBox的实例。lookup()创建KaraokeBox实例吗?实际上,不。其中原因以后解释。

使用RMI,KaraokeBox源代码也要修改。首先要创建Java接口。列表5是KaraokeBox接口的源代码(KaraokeBox.java)。客户机从lookup()接收到的对象类型就是此接口。

列表5:Karaoke box接口(KaraokeBox.java)[RMI]

  interface KaraokeBox extends java.rmi.Remote{
    public void hello(String s) throws java.rmi.RemoteException;
  }

列表6是实现接口的类的源代码(KaraokeBoxImpl.java)。与最初的非分布式对象源代码相比(列表1),它具有更多的代码。

列表6:Karaoke box实现(KaraokeBoxImpl.java)[RMI]

  import java.rmi.*;
  import java.rmi.server.UnicastRemoteObject;

  public class KaraokeBoxImpl extends UnicastRemoteObject implements KaraokeBox{
    public KaraokeBoxImpl() throws RemoteException{
      super();
    }

    public void hello(String s) throws RemoteException{
      System.out.println("Client Name " + s);
    }
 
    public static void main(String argv[]){
      System.setSecurityManager(new RMISecurityManager());
      try{
        KaraokeBox box = new KaraokeBoxImpl();
        java.rmi.Naming.rebind("karaokebox1", box);
      }
      catch(Exception e){e.printStackTrace();}
    }
  }

以下是源代码必要的修改。在RMI中,远程对象用指定的名字(rebind.bind)注册。虽然这些名字不需在源代码中指定,象HORB,RMI使用对象进行远程对象操作,这些对象称为Stub(与HORB中的“代理”等同)和Skeleton.

创建运行环境

RMI有等同于HORB编译器相应部分的功能,这些功能自动创建Stub和Skeleton.

1.> javac Client.java   KaraokeBox.java   KaraokeBoxImpl.java创建

  • Client.class
  • KaraokeBox.class
  • KaraokeBoxImpl.class.

2.> Rmic KaraokeBoxImpl 创建

  • KaraokeBoxImpl_Stub.class
  • KaraokeBoxImpl_Skel.class

3. 将Client.class、KaraokeBox.class和KaraokeBoxImpl_Stub.class拷贝到客户机,将KaraokeBox.class、KaraokeBoxImpl.class、KaraokeBoxImpl_Stub.class和KaraokeBoxImpl_Skel.class拷贝到服务器(在客户机和服务器上必须安装RMI).

运行过程

1.在服务器上启动RMI注册。

2.服务器上启动KaraokeBoxImpl对象。

3.在客户机上以字符串“Junzo”作为参数启动Client。

4.结果“Client Name Junzo”显示在服务器上。

运行结果如图5所示。

图5:RMI运行结果

基础对象模型介绍

这部分用上面的源代码说明HORB和RIM的基础对象模型。基础对象模型是指当一个远程对象产生和使用时,给远程对象用户的视图。在基础对象模型方面,HORB和RMI相差很大。

产生模型[HORB,DCOM]

产生模型提供与面向对象编程一样的实例创建方法。参看列表3中加入的部分(HORB客户机源代码)。下面的列表包括了产生KaraokeBox_Proxy的源代码。

代码1:代理对象创建

 KaraokeBox_Proxy box = new KaraokeBox_Proxy("horb://YourHostName");

回忆一下,KaraokeBox实例也是它的一个运行结果。换句话说,如果你把KaraokeBox_Proxy当作KaraokeBox使用,就可以用面向对象编程中通常的实例产生过程一样的方法创建远程对象。如图6所示。

图6:HORB产生模型

连接模型[CORBA(Java IDL)、RMI、HORB、PDO(NEXTSTEP)]

连接模型用来连接先前由服务器产生的对象。用连接模型,客户机不象在产生模型中那样简单地创建KaraokeBox实例,而是由服务器先创建对象。

将RMI的运行过程与HORB的运行过程比较,很明显,服务器启动KaraokeBoxImpl是为了客户机能够启动Client,如图7所示。

图7:RMI连接模型

下面的列表包括允许客户机连接远程对象的源代码

代码2:连接远程对象

KaraokeBox box =(KaraokeBox)Naming.lookup("rmi://YourHostName/karaokebox1");

在RMI中,在服务器源代码中加入源代码(列表5和列表6)的原因是必须创建Main()方法,以便加入产生远程对象的代码。

几乎所有的分布式对象技术都提供连接模型。HORB既支持产生模型又支持连接模型。连接模型的一个问题是客户机只能连接由服务器产生的对象。为解决此问题,使用了一种技术,在返回客户机之前由服务器创建客户机请求的远程对象。以下是这种技术的一个例子。

代码3:创建客户机请求的远程对象

public KaraokeBox getObject() throws RemoteException{
    KaraokeBox box = null;
    try{
     box = new KaraokeBoxImpl("karaokebox" + instanceNo );
    }
    catch(Exception e){e.printStackTrace();}
     return box;
 }

远程消息

在RMI和HORB中,在远程对象可用后发送一个远程消息的方法几乎是一样的。图8显示了调用hello()方法和往服务器拷贝一个字符串实例(作为hello()方法的参数)。

图8:远程消息

在此处理中,分布式对象系统将String接口转化为简单的数据流,并用低级的Socket类将数据发送给服务器。服务器将String类恢复成以前的形式,这种机制称为“marshalling”和“unmarshalling”。

现在问题是:一个新创建的、独立的类实例能否作为一个远程消息参数或一个返回值?答案在下面关于对象传递的解释中。

对象传递

将对象实例作为一个远程方法的参数传递或作为一个远程方法的返回值称为“对象传递”。作为例子,我们调用KaraokeBox的getMusic()方法,(图9)。客户机作为参数传送歌曲选择数,作为返回值接收相应的Music对象。

图9:Music对象来自服务器

1.由HORB传递对象

首先我们提供一个使用HORB的调用例子。在KaraokeBox中加入了注册getMusic()方法的构造器,并且在初始化时为十首歌加入Music对象。

列表7:Music对象传递(KaraokeBox.java)[HORB]

import java.util.*;
 
 class KaraokeBox{
  Hashtable musicbox = new Hashtable();
   public KaraokeBox(){
     for(int i=0;i < 10;i++){
      musicbox.put( new Integer(i), new Music(i,"Music" + i) ); // Register music
     }
   }
   public void hello(String s){
     System.out.println("Client Name " + s);
   }
  
   public Music getMusic(int select_no){
    Music music = (Music)musicbox.get(new Integer(select_no));
    return music; // Return music for specified song selection number
   }
 }

下面建立Music类,如列表8所示。注意在HORB的当前版本中,在对象中只有公用的“友好”属性(友好属性是没有指定为公用或者私有的属性)才能传递。这限制在支持JDK1.1的HORB下一版本中可能会被取消。

列表8:Music数据管理类(Music.java)[HORB]

public class Music{
    int no = 0;
     String title = "";
     String musicdata = "";
  
     final static String[] SOUNDS = {"Tan", "Bom", "Tata", "Ra-ra"};
  
     public  Music(){}
  
     public  Music(int no,String title){
       this.no = no;
       this.title = title;
       for(int i=0;i < 8;i++){
       musicdata += SOUNDS[(int)(Math.random() * 4)] ;   // Create song (laugh)
       }
      System.out.println("new .." + title + ": " + musicdata );
     }
  
     public int getNo(){
       return no;
     }
  
     public String getTitle(){
       return title;
     }
  
     public void play(){
       System.out.println("start --> " + musicdata + " --> stop");
     }
 }

注意,在HORB当前版本,只能传递不包括保护或私有成员的对象实例,这一限制在支持JDK1.1的HORB下一版本中可能会被取消。就象对hello()方法一样,接收Music对象的代码加入到Client源代码中。

列表9:接收Music对象的版本(Client.java)[HORB]

import horb.orb.*;
 
 class Client{
   public static void main(String argv[]){ 
      String name = (argv.length == 1) ? argv[0] : "-";
      KaraokeBox_Proxy  box = new KaraokeBox_Proxy("horb://kinta");
      box.hello(name);
      for(int i=0;i < 10;i++){
       Music m = box.getMusic(i);      // Object is copied from server
       System.out.print("No." + m.getNo() + " [" + m.getTitle() + "] ");
       m.play();
      }
     }
 }

创建运行环境

用HORB命令编译Music.java和KaraokeBox.java和用javac编译Client.java的过程如下。注意Music.java必须用HORB编译。如不用HORB传递对象,必须用一个代理。为了以后简单,确定按下面的方法指定HORB编译器选项,使之不产生不必要的源代码和类。

1.>horbc-delete -proxyonly Music.java 创建

  • Music.class
  • Music_proxy.class.

2.>horbc -delete KaraokeBox.java 创建

  • KaraokeBox.class
  • KaraokeBox_Proxy.class
  • KaraokeBox_Skeleton.class

3.>javac Client.java 创建

  • Client.class
  • horbc 选项:

-proxyonly产生一个Proxy类,不产生Skeleton类。

-Delete删除Skeleton和Proxy源代码。

运行过程

1.在服务器上启动HORB精灵。

2.在客户机上用字符串“Junzo”作为参数启动Client

3.十个音乐数据项显示在服务器和客户机上。

运行结果如图10所示。

图10:HORB运行结果(对象传递)

2.用RMI传递对象

第一步是增加KaraokeBox加载,以及和用HORB一样,getMusic()方法和Music对象注册的代码。另外,KaraokeBox和KaraokeBoxImpl的源代码也必须修改(参看列表10和列表11)。

列表10:KaraokeBox接口(KaraokeBox.java)[RMI]

interface KaraokeBox extends java.rmi.Remote{
    public void hello(String s) throws java.rmi.RemoteException;
    public Music getMusic(int select_no) throws java.rmi.RemoteException;
 }

列表11:Music对象传递(KaraokeBoxImpl.java)[RMI]

import java.rmi.*;
import java.rmi.server.UnicastRemoteObject;
 import java.util.Hashtable;
 
 public class KaraokeBoxImpl extends UnicastRemoteObject implements KaraokeBox{
     private Hashtable musicbox = new Hashtable();
     public KaraokeBoxImpl() throws RemoteException{
       super();
       for(int i=0;i < 10;i++){
        musicbox.put( new Integer(i), new Music(i,"Music" + i) ); // Register music
       }
     }
  
     public void hello(String s) throws RemoteException{
     System.out.println("Client Name " + s);
     }
  
     public Music getMusic(int select_no) throws RemoteException{
       Music music = (Music)musicbox.get(new Integer(select_no));
       return music;  // Return music for specified song selection number
     }
  
     public static void main(String argv[]){
       try{
       KaraokeBox box = new KaraokeBoxImpl();
       System.setSecurityManager(new RMISecurityManager());
       java.rmi.Naming.rebind("karaokebox1", box);
       }
       catch(Exception e){e.printStackTrace();}
     }
 }

RMI对象传递中使用了JDK1.1的串行化功能。Music类必须实现java.io.SerializableJava接口(参看列表12)。不象HORB,RMI允许传递有私有成员的对象。

列表12:Music数据管理类(Music.java)[RMI]

public class Music implements java.io.Serializable{
     private int no = 0;
     private String title = "";
     private String musicdata = "";
     private final static String[] SOUNDS = {"Tan", "Bom", "Tata", "Ra-ra"};
  
     public  Music(int no,String title){
       this.no = no;
       this.title = title;
       for(int i=0;i < 8;i++){      
        musicdata += SOUNDS[(int)(Math.random() * 4)] ;  // Compose song (laugh)
       }
  
       System.out.println("new .." + title + ": " + musicdata );
     }
  
     public int getNo(){
       return no;
     }
  
     public String getTitle(){
       return title;
     }
  
     public void play(){
       System.out.println("start --> " + musicdata + " --> stop");
     }
 }

与HORB一样,接收Music对象的代码加到了客户机的源代码中,如列表13所示。

列表13:接收版本的Music对象(Client.java)[RMI]

class Client{
   public static void main(String argv[]){
      String name = (argv.length == 1) ? argv[0] : "-";
      try{
       KaraokeBox box = (KaraokeBox)java.rmi.Naming.lookup("rmi://kinta/karaokebox1");
       box.hello(name);
       for(int i=0;i < 10;i++){
     Music m = box.getMusic(i);
           System.out.print("No." + m.getNo() + " [" + m.getTitle() + "] ");
     m.play();
       }
      }
      catch(Exception e){e.printStackTrace();}
    }
 }

创建运行环境

不象用HORB,而与往常一样用javac编译Music.java

1.>Javac Music.java Client.java KaraokeBox.java KaraokeBoxImpl.java

2.> rmic KaraokeBoxImpl

运行过程

1.在服务器上启动RMI注册。

2.在服务器上启动KaraokeBoxImpl远程对象。

3.十个音乐数据项显示在服务器上。

4.在客户机上以字符串“Junzo”作为参数启动Client。

5.十个音乐数据项显示在客户机上。运行结果如图11所示(在示例代码中,“lookup”(第四步)必须在“rebind”(第三步)结束后运行)。

图11:RMI运行结果(对象传递)

分布式应用程序的设计

以下是在设计分布式应用程序时需要考虑的几点:

理解产品的特征

在开发分布式应用程序时重要的一点是掌握使用的分布式对象的一般特征。最好的办法是将你的产品与其他的、已存在的产品比较。另外,还需要理解产品的概念。例如HORB追求一种无缝的、分布式的面向对象环境,所以列表1中介绍的KaraokeBox类无需为远程服务器设计而修改。另外,使用KaraokeBox类的客户机与本地对象一样──调用new。即使在远程方法调用时,程序员在编码时无需使用异常处理。

比较而言,RMI要求程序员按照精确的规则设计分布式对象,以提高软件的整体可靠性。例如设计远程对象时,程序必须使用Java接口,与本地方法一样对对象明确分类。另外,在远程方法调用中,程序员必须处理异常。与HORB的另一个差别是父类是在远程对象中决定的。

若要问哪一个是当前最好的方案,我们更倾向HORB网络无缝的概念。当然,每个人都有个人的偏爱,未必能有一个客观的评价。HORB也提供很高的可靠性,而RMI和HORB一样,一但你习惯了它也会很容易使用。

这时与其讨论谁优谁劣,不如客观地比较HORB和RMI。这样我们便可以理解所使用的分布式对象技术创造者的目的。在弥补其不足时,理解软件。同时,洞查分布式对象未来的形式。总之,符合发展趋势的便是最好的方案。

明确指出分布式处理的目标

决定哪一项设为远程对象是很重要的一点。将单机内存对象扩展到网络上便成了分布式对象。设计远程对象时,程序员还要考虑涉及到的其他问题。具体地说,程序员必须考虑诸如在远程处理时尽量减少网络传输量和使客户机与远程对象接口尽可能小等问题。建立一个系统时,为了有一个平衡的设计,必须考虑在网络中包括分布式对象的需求。

正确使用对象传递和远程对象

正确的使用对象传递和远程对象也是很重要的一点。远程对象是通过代理访问服务器对象的一种方法。例如,上面介绍的Music对象的例子,处理是通过将Music对象作为远程对象装载,而不是使用对象传递实现的。只有CORBA支持这种方法。

对象传递允许程序员减少通信,因为对象被拷贝到了客户机上。远程对象更适合用于需要直接利用服务器CPU资源或服务器数据资源的情况。从数据一致性的观点来说,当客户机只需要对象的一些属性,而不是整个对象时,更适合用远程对象。在服务器对象属性总由服务器处理来修改的模型中,也更适合用远程对象。

作为面向对象方法学的一环

分布目标清楚的设计应该用面向对象的分析无缝地实现。将来,网络分布式对象模型可能会成为面向对象方法学中开发过程的一环。在由作者开发的面向对象方法学“Drop”中(http://www.njk.co.jp/otg/),这类环境通过使用在对象分析中称为“重用基础模型”的对象分类方法来实现。重用基础模型是一种分类方法,将需求分析阶段的对象分成不同的角色,如View(视图)、Process(处理)和Data(数据管理)。并且分清重用范围,如Generic(通用)、Addparts(系统公用)和App(应用程序专用),这种模式可用来对需求分析阶段的对象分类,并且转换为无缝的分布式对象设计。

用CORBA设计

这部分介绍一个Music类的例子,它是CORBA设计的。CORBA使用远程对象来装载Music对象。在此情况下,当客户机调用Music对象的参考(在CORBA中为代理对象)的play()方法时,play()方法由服务器运行。这是不方便的。实际上,Music类的play()方法必须修改为命名为getMusicData()的方法。Music的数据结构(而不是对象)必须传递到客户机上。客户机必须创建一个新的Player类。使用Player对象来修改使用Music数据的设计。换句话说,play()方法不能进入到分布在服务器的对象中(参看图12)

图12:将音乐数据传给播放器

在此例子中,Music类变成了一个数据管理数据对象,Player类变成了一个播放处理。换句话说“Drop”不提倡将称为play()的播放处理指派给Music数据管理对象的设计。(在本文中,我们将play()指派给Music,以简化说明。)

通过在分析的开始便将数据管理数据和数据操作过程分开,以及集中于数据管理对象,我们能解决因为分布式对象产品的差别而不得不修改设计方法的问题。同时我们能将调用方法排除在基本问题的分析阶段。

去年,作者所属的开发组使用了“Drop”开发过程开发了一个航空订票系统。在系统活动期间,通过使用称为“concept”的概念,同时执行中间软件认证和网络框架检查,转变了分布式对象或数据库的调用方法。

现在,这个开发组通过讨论会和Web站点,将航空系统用来介绍基于分布式对象的网络系统的设计。今年,我们计划用讨论会来培训将来支持软件业务的学员。

分布式对象编程的目标

分布式对象编程的目标是将基于单机的面向对象机制扩展到网络,实现此目标可以归结为以下三个技术概念:

1.网络透明的面向对象操作-允许用正常的面向对象编程方法操作对象。

2.对象位置透明性-提供一个隐藏网络上对象位置(服务器)的机制。

3.语言独立、ORB产品独立的环境-提供一个不依赖于特定语言和产品的环境。

第一个概念,网络透明的面向对象操作是HORB大力提倡的。然而,HORB不支持上面的概念2或3-对象位置的透明性和语言独立、ORB产品独立的环境。

HORB概念将分布式对象当作面向对象的扩充。RMI也不支持概念2或3,然而RMI概念接近于CORBA对象模型,似乎与HORB一样也强调以上所列的第一个概念。另一方面,CORBA大力提倡概念2和3。自1990年以来,对象管理集团(OMG)一直在发展CORBA,使之成为分布式对象编程的全球标准。当前的CORBA版本为2.0。一个称为JavaIDL(接口定义语言)、符合CORBA的ORB捆绑在JDK1.1中。CORBA概念,例如开放软件基金会(OSF)的远程过程调用(RPC)和分布式计算环境(DCE),将分布式对象看作是网络计算的扩充。因此,CORBA重点在于技术概念2和3,它们面向大规模的、分布的网络系统。然而,仍不能说CORBA已实现了“网络透明对象操作”的目标。

例如,我们看看CORBA的公用语言-IDL。必须用此语言声明远程消息。IDL是一个重要的框架,允许在包括不同的ORB和语言的环境中进行协同对象操作。然而,使用IDL类似于开发一个名为Esperanto的语言的概念,它允许全球的每一个人用一种公用语言交谈。使用一种公用语言可能会导致一个国家成熟的发展减弱(例如一种语言成熟的面向对象功能)。而且,如果ORB开发商完全实现CORBA大部分的规范,将面临无穷无尽的工作。

虽然,每一个分布式对象工具有不同的结构,但是下一代分布式对象应用程序可能会以很好地平衡如上所述的三个技术概念为特征。为实现这一步的工作已经开始,一些CORBA产品对用户隐藏IDL,也有一些非CORBA产品支持CORBA的Internet交互对象请求代理协议(IIOP),以便能够连接CORBA。虽然这些工作被认为是一些调整,但是它们可能是产生下一代分布式对象产品的开发过程不可分割的部分。

结论

本文叙述了基于Java的分布式对象技术RMI和HORB。有很多我们想介绍的功能,例如RMI和HORB支持双向消息通信和HORB支持的异步通信,以及很多新的符合CORBA的、基于Java的分布式对象产品,但是限于篇幅,我们就到这。虽然分布式对象编程并不难,但是它是使复杂网络应用程序易于理解的领先技术。