发信人: daystream()
整理人: biubiu(2000-01-04 11:48:09), 站内信件
|
远程对象激活
---------------------------------------------------------------------- ----------
第 7 章
主题:
概述
激活协议
“可激活”远程对象的实现模型
激活接口
.1 概述
分布式对象系统被设计为支持长期存在的持久对象。假设这些系统将由成千(也 许成万)个这样的对象组成,则对象的实现在无限期的时间段内被激活并保持活 动状态是不合理的。这将占用宝贵的系统资源。另外,客户机需要保存对对象的 持久引用的能力,这样在一个系统崩溃后可以重新建立对象之间的通讯,因为通 常对一个分布对象的引用只有当对象处于活动状态时才有效。
对象激活是一种用来提供对对象持久引用和管理对象实现的执行的机制。在 RMI 中,激活允许对象根据需要开始执行。当访问(通过方法调用)“可激活”远程 对象时,如果该远程对象当前尚未执行,则系统将在适当的 Java 虚拟机中开始 该对象的执行。
7.1.1 术语
活动 (active) 对象是在某些系统的 Java 虚拟机中被实例化并被导出的远程对 象。非活动对象在虚拟机中尚未被实例化(或导出),但能变成活动状态的远程 对象。激活就是将非活动对象转化为活动对象的过程。激活要求对象与一台虚拟 机相关联,而这将可能需要将该对象的类加载到虚拟机中,同时该对象也恢复其 持久状态(如果有)。
在 RMI 系统中,我们使用了惰性激活。惰性激活就是将一个对象的激活延迟到客 户机第一次使用该对象时(即第一次方法调用时)。
7.1.2 惰性激活
远程对象的惰性激活是用不完善远程引用(有时称为不完善块)实现的。对远程 对象的不完善远程引用在第一次调用对象的方法时,“完善”为活动对象的引用 。每个不完善引用均保持一个持久句柄(激活标识符)和对目标远程对象的瞬态 远程引用。远程对象的激活标识符包含足够的信息来使第三方激活该对象。瞬态 引用是对可用来联系执行对象的主动远程对象的“活动”引用。
在不完善引用中,如果对远程对象的活引用为空,则不认为目标对象是主动的。 在方法调用中,不完善引用(对该对象)将加入激活协议以获得“活”引用,该 引用是对新激活的对象的远程引用(例如单路传送 (unicast) 的远程引用)。一 旦不完善引用得到活引用,则不完善引用将把方法调用传给底层的远程引用,而 该远程引用又将方法调用传给远程对象。
具体的说,远程对象的 stub 包含一个“不完善”远程引用类型,该类型既包括 :
远程对象的激活标识符,又包括
“活”引用(可能为空),其中包含远程对象的“活动”远程引用类型(例如, 带有单路传送语义的远程引用类型)。
---------------------------------------------------------------------- ----------
注意 - RMI 系统对远程调用保留“至多一次”语义。换句话说,对可激活或单路 传送远程对象的调用将至多发送一次。因此,如果对远程对象的调用失败(由抛 出的 RemoteException 异常表示),则客户机将得到如下保证:远程方法的执行 不会超过一次,甚至根本就不执行。
7.2 激活协议
在远程方法调用期间,如果目标对象的“活”(live) 引用是未知的,则不完善引 用将使用激活协议。激活协议包括下列几个实体:不完善引用、激活器、Java 虚 拟机中的激活组和被激活的远程对象。
激活器(通常每个主机有一个)是一个实体,负责激活,它是:
将激活标识符映射到激活对象所需信息(对象的类、位置 -- URL 路径 -- 从该 处可加载类、对象可能需要用于自举 (bootstrap) 的特定数据等)的信息数据库 ,及
Java 虚拟机的管理器,它启动虚拟机(必要时)并将对象激活请求(和必要的信 息一起)传送到远程虚拟机中正确的激活组。
注意:激活器始终将激活标识符到活动对象的当前映射保存在缓存中,这样就无 需为每个激活请求而查询该组。
激活组(每个 Java 虚拟机中一个)是这样的实体,它接收对激活 Java 虚拟机 中对象的请求并将激活的对象返给激活器。
激活协议如下所示。不完善引用使用一个激活标识符并调用激活器(内部 RMI 接 口)来激活与该标识符关联的对象。激活器查找对象的激活描述符(先前已注册 )。对象的描述符包括:
对象的组标识符(指定对象激活时所处的虚拟机),
对象的类名,
URL 路径,从该处加载对象的类代码,
特定于对象的已编组的初始化数据(例如,初始化数据可能是包含对象持久状态 的文件的名称)。
如果应容纳该对象的激活组存在,则激活器将激活请求传送到该组。如果激活组 不存在,则激活器将启动虚拟机以执行激活组,然后将激活请求传送到该组。
激活组将加载对象的类并用特定的构造函数来实例化该对象。此构造函数带多个 参数,包括先前注册的激活描述符。
对象完成激活时,激活组将把已编组对象引用传回激活器,然后该激活器记录激 活标识符和激活引用对,并将活动(活)引用返给不完善引用。随后,不完善引 用(在 stub 内)通过活动引用将方法调用直接传给远程对象。
---------------------------------------------------------------------- ----------
注意 - 在 JDK 中,RMI 提供激活系统接口的实现。要使用激活,必须首先运行 激活系统守护进程 (daemon) rmid。
7.3 “可激活”远程对象的实现模型
为了使可通过激活标识符访问的远程对象不受时间影响,开发人员必须做到:
为该远程对象注册一个激活描述符
在对象的类中包含一个专用构造函数,当 RMI 系统激活可激活对象时将调用它。
可用以下几种方法来注册激活描述符 (ActivationDesc):
调用类 Activatable 的静态 register 方法
用 Activatable 类的第一个或第二个构造函数创建“可激活”对象
显式地导出“可激活”对象。该过程可用 Activatable 的第一个或第二个 expo rtObject 方法实现,其参数为 ActivationDesc、Remote 对象的实现和端口号。
对于特定对象,只可用上述三种方法之一来注册激活对象。有关如何实现可激活 对象的示例,请参阅后面的“构造可激活远程对象”。
7.3.1 ActivationDesc 类
ActivationDesc 含有激活对象所需的信息。它包含对象的激活组标识符、对象的 类名、加载对象代码的 codebase 路径(或 URL)及 MarshalledObject(可包含 每次激活期间所用的对象特定初始化数据)。
激活过程中将查询在激活系统中注册的描述符以获取有关的信息,从而用于重新 创建或激活对象。对象的描述符中的 MarshalledObject 将作为第二个参数传给 远程对象的构造函数,以供激活过程使用。
package java.rmi.activation;
public final class ActivationDesc implements java.io.Serializable
{
public ActivationDesc(String className,
String codebase,
java.rmi.MarshalledObject data)
throws ActivationException;
public ActivationDesc(String className,
String codebase,
java.rmi.MarshalledObject data,
boolean restart)
throws ActivationException;
public ActivationDesc(ActivationGroupID groupID,
String className,
String codebase,
java.rmi.MarshalledObject data,
boolean restart);
public ActivationDesc(ActivationGroupID groupID,
String className,
String codebase,
java.rmi.MarshalledObject data);
public ActivationGroupID getGroupID();
public String getClassName();
public String getLocation();
public java.rmi.MarshalledObject getData()
public boolean getRestartMode();
}
ActivationDesc 的第一个构造函数构造一个对象的对象描述符,这个对象的类是 className(可从 codebase 路径加载),它的初始化信息(已编组形式)为 d ata。如果使用这种形式的构造函数,则对象的组标识符缺省为该虚拟机 Activa tionGroup 的当前标识符。具有相同 ActivationGroupID 的所有对象都将在同一 虚拟机中被激活。如果当前组是非活动的或无法创建缺省组,则将抛出 Activat ionException。如果 groupID 为 null,则将抛出 IllegalArgumentException。
---------------------------------------------------------------------- ----------
注意 - 作为创建 ActivationDesc 的副效应,如果该虚拟机的 ActivationGrou p 当前不是活动的,则将创建缺省 ActivationGroup。缺省激活组将 java.rmi. RMISecurityManager 作为安全管理器,并在重新激活时将激活组虚拟机中的属性 设置为该虚拟机中的当前属性。如果应用程序需用不同的安全管理器,则在创建 缺省 ActivationDesc 之前必须设置该虚拟机的组。有关如何为虚拟机创建 Act ivationGroup 的详细信息,参见方法 ActivationGroup.createGroup。
---------------------------------------------------------------------- ----------
ActivationDesc 第二个构造函数构造对象描述符的方式与第一个构造函数相同, 但必须提供附加的参数 restart。如果对象要求重启服务,这意味着当激活器重 新启动时,对象也会自动重新启动(与根据需要激活的惰性激活相反)。此时, restart 应为 true。如果 restart 为 false,则对象将只是在需要时激活(通 过远程方法调用)。
ActivationDesc 的第三个构造函数构造一个对象的对象描述符。这个对象的组标 识符为 groupID,它的类名为 className(可从 codebase 路径加载),它的初 始化信息为 data。所有具有相同 groupID 的对象都将在同一 Java 虚拟机中被 激活。
ActivationDesc 第四个构造函数构造对象描述符的方式与第三个构造函数相同, 但它允许指定重启模式。如果对象需要重新启动(定义如上),则 restart 应为 true。
getGroupID 方法返回该描述符所指定对象的组标识符。组可以提供一种将对象聚 合到单一 Java 虚拟机中的方法。
getClassName 方法返回该激活描述符所指定对象的类名。
getLocation 方法返回用于下载该对象的类的 codebase 路径。
getData 方法返回一个“已编组对象”,该编组对象包含用于初始化(激活)描 述符指定的对象的数据。
getRestartMode 方法在该对象的重启模式启用时返回 true,否则返回 false。
7.3.2 ActivationID 类
激活协议利用激活标识符来表示不受时间影响的可激活远程对象。激活标识符( 类 ActivationID 的实例)含有激活对象所需的若干信息:
对象激活器的远程引用
对象的唯一标识符。
对象的激活标识符可通过向激活系统注册对象来得到。可用下述几种方法之一来 完成注册(如上所述):
通过 Activatable.register 方法
通过第一个或第二个 Activatable 构造函数(都有三个参数而且注册并导出对象 )
通过第一个或第二个 Activatable.exportObject 方法(它们以激活描述符、对 象实现及端口为参数,且都注册并导出对象)。
package java.rmi.activation;
public class ActivationID implements java.io.Serializable
{
public ActivationID(Activator activator);
public Remote activate(boolean force)
throws ActivationException, UnknownObjectException,
java.rmi.RemoteException;
public boolean equals(Object obj);
public int hashCode();
}
ActivationID 的构造函数接受参数 activator,该参数指定对激活器(负责激活 与该激活标识符关联的对象)的远程引用。ActivationID 的实例是全局唯一的。
activate 方法将激活与该激活标识符关联的对象。如果 force 参数为 true,激 活器将把远程对象的任何高速缓存引用视为已过时,从而迫使激活器在激活对象 时与组联系。如果 force 为 false,则返回可接受的高速缓存值。如果激活失败 ,则抛出 ActivationException。如果激活器不能识别该对象标识符,则该方法 将抛出 UnknownObjectException。如果对激活器的远程调用失败,则抛出 Remo teException。
equals 方法可实现基于内容的相等比较。如果所有的域都相等(完全相同或从各 域的 Object.equals 语义上等价),它将返回 true。如果 p1 和 p2 是类 Act ivationID 的实例,则在 p1.equals(p2) 返回 true 时 hashCode 方法返回相同 的值。
7.3.3 Activatable 类
Activatable 类提供对需要持久访问而不受时间影响,同时又被系统激活的远程 对象的支持。类 Activatable 是开发人员用来实现和管理可激活对象的主要应用 程序接口。注意,必须先运行激活系统守护进程 rmid,然后才能注册和/或激活 对象。
package java.rmi.activation;
public abstract class Activatable
extends java.rmi.server.RemoteServer
{
protected Activatable(String codebase,
java.rmi.MarshalledObject data,
boolean restart,
int port)
throws ActivationException, java.rmi.RemoteException;
protected Activatable(String codebase,
java.rmi.MarshalledObject data,
boolean restart,
int port,
RMIClientSocketFactory csf,
RMIServerSocketFactory ssf)
throws ActivationException, java.rmi.RemoteException;
protected Activatable(ActivationID id, int port)
throws java.rmi.RemoteException;
protected Activatable(ActivationID id, int port,
RMIClientSocketFactory csf,
RMIServerSocketFactory ssf)
throws java.rmi.RemoteException;
protected ActivationID getID();
public static Remote register(ActivationDesc desc)
throws UnknownGroupException, ActivationException,
java.rmi.RemoteException;
public static boolean inactive(ActivationID id)
throws UnknownObjectException, ActivationException,
java.rmi.RemoteException;
public static void unregister(ActivationID id)
throws UnknownObjectException, ActivationException,
java.rmi.RemoteException;
public static ActivationID exportObject(Remote obj,
String codebase,
MarshalledObject data,
boolean restart,
int port)
throws ActivationException, java.rmi.RemoteException;
public static ActivationID exportObject(Remote obj,
String codebase,
MarshalledObject data,
boolean restart,
int port,
RMIClientSocketFactory csf,
RMIServerSocketFactory ssf)
throws ActivationException, java.rmi.RemoteException;
public static Remote exportObject(Remote obj,
ActivationID id,
int port)
throws java.rmi.RemoteException;
public static Remote exportObject(Remote obj,
ActivationID id,
int port,
RMIClientSocketFactory csf,
RMIServerSocketFactory ssf)
throws java.rmi.RemoteException;
public static boolean unexportObject(Remote obj, boolean force)
throws java.rmi.NoSuchObjectException;
}
可激活远程对象的实现可能扩展或不扩展类 Activatable。确实扩展 Activatab le 类的远程对象实现将从超类 java.rmi.server.RemoteObject 中继承 hashCo de 和 equals 方法中的相应定义。因此,引用同一 Activatable 远程对象的两 个远程引用是相等的(equals 方法将返回 true)。同样,类 Activatable 的实 例将“等于”该实例的相应 stub 对象(即如果 Object.equals 方法用与该实现 匹配的 stub 对象作为参数进行调用,它将返回 true。反之亦然)。
Activatable 类方法
Activatable 类的第一个构造函数用于在指定 port 上注册和导出对象(如果 p ort 为零,则选用某个匿名端口)。下载的类代码对象的 URL 路径是 codbase, 其初始化数据是 data。如果 restart 为 true,则对象将在激活器重新启动或组 失效时自动重新启动。如果 restart 为 false,则对象将根据需要而激活(通过 对对象的远程方法调用)。
Activatable 类的具体子类必须调用该构造函数才能在初始构造期间注册和导出 该对象。作为构造可激活对象时的副效应,远程对象将被“注册”到激活系统上 并“导出”(如果 port 为零,则在匿名端口导出)到 RMI 运行时,从而使之可 接受来自客户机的到来调用。
如果向激活系统注册对象失败,则该构造函数将抛出 ActivationException。如 果将对象导出到 RMI 运行时失败,则将抛出 RemoteException。
第二个构造函数与第一个 Activatable 构造函数相同,但它允许将客户机和服务 器套接字工厂规范用于与该可激活对象进行通讯。详细信息,参见“RMI 套接字 工厂”。
第三个构造函数用于激活对象并从指定的 port 将其(用 ActivationID,id)导 出。当对象本身被其专用的“激活”构造函数激活时,Activatable 类的具体子 类必须调用该构造函数。该“激活”构造函数的参数必须是:
对象的激活标识符 (ActivationID) 及
对象的初始化/自举数据 (MarshalledObject)。
作为构造的副效应,远程对象将被“导出”到 RMI 运行时中(从指定 port)并 可接受来自客户机的调用。如果将对象导出到 RMI 运行时失败,则该构造函数将 抛出 RemoteException。
第四个构造函数与第三个构造函数相同,但它允许将客户机和服务器套接字工厂 规范用于与该可激活对象进行通讯。
getID 方法返回对象的激活标识符。该方法是受保护的,因而只有子类才能获取 对象的标识符。 对象的标识符用于报告对象的非活动状态或注销对象的激活描述 符。
register 方法为可激活的远程对象向激活系统注册对象描述符 desc,从而使该 对象能在需要时被激活。该方法可用于注册可激活对象而无需先创建该对象。它 返回可激活对象的 Remote stub,因此可加以保存并在今后调用,从而强制首次 创建/激活该对象。如果没有向激活系统注册 desc 中的组标识符,该方法将抛出 UnknownGroupException。如果激活系统未运行,则抛出 ActivationException 。最后,如果对激活系统的远程调用失败,则抛出 RemoteException。
inactive 方法用于通知系统具有相应激活 id 的对象当前是非活动的。如果已知 该对象当前是活动的,则该对象将不从 RMI 运行时环境中导出(仅在没有待定的 或执行的调用时),从而可不再接收到来的调用。该调用还将通知该虚拟机的 A ctivationGroup 该对象处于非活动状态;而该组又将通知其 ActivationMonito r。如果该调用成功,则此后对激活器的激活请求将导致重新激活该对象。如果成 功地阻止该对象被导出(意味着此时它没有待定或执行调用),则 inactive 方 法返回 true;如果由于待定或进程内调用而不能阻止该对象被导出,则返回 fa lse。如果对象是未知的(它可能是非活动的),则该方法将抛出 UnknownObjec tException;如果组是非活动的,则抛出 ActivationException;如果通知显示 器的调用失败,则抛出 RemoteException。如果该对象被认为是活动的但已自己 阻止导出,则该操作仍将成功进行。
unregister 方法用于撤消与 id 关联的激活描述符的先前注册。对象不能再用这 个 id 来激活。如果该对象 id 对激活系统来说是未知的,则抛出 UnknownObje ctException。如果激活系统未处于运行状态,则抛出 ActivationException。如 果对激活系统的远程调用失败,则抛出 RemoteException。
第一个 exportObject 方法可被“可激活”但不扩展 Activatable 类的对象显式 调用,其目的是:a) 向激活系统注册对象的激活描述符 desc,由所提供的 cod ebase 和 data 构造(因此可激活该对象);b) 从指定 port 导出远程对象 ob j(如果该 port 为零,则将选择匿名端口)。对象一旦被导出,即可接收到来的 调用。
该 exportObject 方法返回向激活系统注册描述符 desc 时所获得的激活标识符 。如果在虚拟机中激活组不是活动的,则抛出 ActivationException。如果对象 注册或导出失败,则抛出 RemoteException。
如果 obj 扩展 Activatable,则不必调用该方法,因为第一个 Activatable 构 造函数将调用该方法。
第二个 exportObject 方法与第一个相同,但它允许将客户机和服务器套接字工 厂规范用于与该可激活对象进行通讯。
第三个 exportObject 方法将带标识符 id 的“可激活”远程对象(不一定是 A ctivatable 类型的)导出到 RMI 运行时,以使对象 obj 能够接收到来的调用。 如果 port 为零,则将在某个匿名端口导出该对象。
激活时,不扩展 Activatable 类的“可激活”对象应显式地调用此 exportObje ct 方法。确实扩展 Activatable 类的对象不必直接调用该方法;它将被上面的 第三个构造函数所调用(应从其专用的激活构造函数中调用子类)。
该 exportObject 方法将返回可激活对象的 Remote stub。如果该对象的导出失 败,则该方法将抛出 RemoteException。
第四个 exportObject 方法与第三个相同,但它允许将客户机和服务器套接字工 厂规范用于与该可激活对象进行通讯。
unexportObject 方法使远程对象 obj 不能接收到来的调用。如果参数 force 为 true,则即使有对远程对象的待定调用或远程对象在进程内仍有调用,对象也将 被强制阻止导出。如果参数 force 为 false,则只在没有对对象的待定调用或进 程内没有调用时它才被阻止导出。如果成功地阻止了该对象的导出,则 RMI 运行 时将从其内部表中删掉它。使用这种强制方式从 RMI 删除对象可能会使客户机持 有远程对象的过时远程引用。如果此前没有将对象导出到 RMI 运行时,则该方法 将抛出 java.rmi.NoSuchObjectException。
构造可激活的远程对象
为了使对象可激活,“可激活”对象实现类不管是否扩展 Activatable 类,都必 须定义一个特殊的公共构造函数。该公共构造函数带有两个参数:激活标识符( 类型为 ActivationID)及激活数据 java.rmi.MarshalledObject(在注册时所用 的激活描述符中提供)。当激活组在其虚拟机内激活某个远程对象时,它将利用 此特殊构造函数来构造对象(后面将作详细说明)。远程对象实现可适当用激活 数据来初始化自己。远程对象也可能想保留其激活标识符,这样就可以在它变为 非活动状态(通过对 Activatable. inactive 方法的调用)时通知激活组。
Activatable 构造函数的第一种和第二种形式用于从指定的 port 注册并导出可 激活对象。最初构造对象时应使用该构造函数;该构造函数的第三种形式将在重 新激活对象时使用。
Activatable 的具体子类必须在最初构造期间调用第一种或第二种构造函数以注 册并导出对象。 构造函数首先用对象的类名创建一个激活描述符 (ActivationD esc)、对象所提供的 codebase 和 data(其激活组为虚拟机的缺省激活组)。然 后,构造函数将向缺省的 ActivationSystem 注册该描述符。最后,构造函数在 特定 port 上(如果 port 为零,则选择匿名端口)将可激活对象导出到 RMI 运 行时中,并将该对象作为 activeObject 报告给本地 ActivationGroup。如果在 注册或导出的过程中出错,则构造函数抛出 RemoteException。注意,构造函数 也初始化它的 ActivationID(通过注册获得),因此接下来对 protected 方法 getID 的调用将返回对象的激活标识符。
Activatable 构造函数的第三种形式用于从指定的端口导出对象。当 Activatab le 的具体子类被对象自己的“激活”构造函数激活时,必须调用第三种构造函数 。该“激活”构造函数带两个参数:
对象的 ActivationID
对象的初始化数据,一个 MarshalledObject 对象
该构造函数只将可激活对象从特定 port(如果 port 为零,则选择匿名端口)导 出到 RMI 运行时中,而并不通知 ActivationGroup 该对象已是活动对象。因为 正是 ActivationGroup 激活该对象的,因而它自然知道对象已处活动状态。
下面是远程对象接口 Server 和扩展 Activatable 类的实现 ServerImpl 的示例 :
package examples;
public interface Server extends java.rmi.Remote {
public void doImportantStuff()
throws java.rmi.RemoteException;
}
public class ServerImpl extends Activatable implements Server
{
// 初始构造、注册及导出时的构造函数
public ServerImpl(String codebase, MarshalledObject data)
throws ActivationException, java.rmi.RemoteException
{
// 向激活系统注册对象,然后
// 在匿名端口上导出
super(codebase, data, false, 0);
}
// 激活及导出的构造函数。该构造函数由
// ActivationInstantiator.newInstance
// 方法在激活过程中所调用,以构造对象
public ServerImpl(ActivationID id, MarshalledObject data)
throws java.rmi.RemoteException
{
// 调用父类的构造函数以
// 将对象导出到 RMI 运行时。
super(id, 0);
// 初始化对象(例如利用数据)
}
public void doImportantStuff() { ... }
}
对象将负责导出自己。Activatable 的构造函数负责将对象导出到具有活动引用 类型 UnicastRemoteObject 的 RMI 运行时中,因此,扩展 Activatable 的对象 实现不必关心显式导出对象(不是调用相应的超类构造函数)的具体细节。如果 对象实现不扩展类 Activatable,则该对象必须通过调用某个 Activatable.exp ortObject 静态方法来显式导出该对象。
下例中,ServerImpl 不扩展 Activatable,而是扩展另一个类。因此,ServerI mpl 负责在初始构造和激活过程中导出自己。下述的类定义给出了 ServerImpl 的初始化构造函数及其特殊“激活”构造函数,以及每个构造函数内用于导出对 象的相应调用:
package examples;
public class ServerImpl extends SomeClass implements Server
{
// 初始创建时的构造函数
public ServerImpl(String codebase, MarshalledObject data)
throws ActivationException, java.rmi.RemoteException
{
// 注册并导出对象
Activatable.exportObject(this, codebase, data, false, 0);
}
// 激活的构造函数
public ServerImpl(ActivationID id, MarshalledObject data)
throws java.rmi.RemoteException
{
// 导出对象
Activatable.exportObject(this, id, 0);
}
public void doImportantStuff() { ... }
}
在不创建对象的情况下注册激活描述符
要在不创建对象的情况下向激活系统注册可激活远程对象,程序员只需为对象注 册激活描述符(类 ActivationDesc 的实例)。激活描述符含有一切所需的信息 ,因此必要时激活系统就可以激活该对象。可用以下方法来注册类 examples.Se rverImpl 实例的激活描述符(忽略异常处理):
Server server;ActivationDesc desc;String codebase = "http://zaphod/cod ebase/";
MarshalledObject data = new MarshalledObject("some data");desc = new A ctivationDesc( "examples.ServerImpl", codebase, data);server = (Server )Activatable.register(desc);
register 调用将返回一个 Remote stub(它是 examples.ServerImpl 对象的 s tub),并实现一组与 examples.ServerImpl 所实现的远程接口相同的远程接口 (即 stub 实现远程接口 Server)。该 stub 对象(上述被强制类型转换并指派 给 server 的对象)可作为参数传给期望实现 examples.Server 远程接口的对象 的任何方法调用。
-- ※ 来源:.月光软件站 http://www.moon-soft.com.[FROM: 202.96.191.124]
|
|