RMI(基本概念)
Java Remote Method Invocation ( RMI -- Java 远程方法调用)允许您使用Java 编写分布式对象,不同的Java 虚拟机(JVM)之间进行对象间的通讯。这些JVM 可以在一台者多台计算机上,使得应用程序(Application) 可以远程调用方法,共享各个系统的资源和处理能力。
RMI 的主要优点
面向对象:
RMI 可将完整的对象作为参数和返回值进行传递。您可以将类似Java HashTabl e
这样的复杂类型作为一个参数进行传递。
可移动属性:
RMI 可将属性(类实现程序)从客户机移动到服务器,或者从服务器移到客户机。
便于编写和使用:
RMI 使得Java 远程服务程序和访问这些服务程序的Java 客户程序的编写工作变得轻松、简单。
服务程序大约用三行指令宣布本身是服务程序,其它方面则与任何其它Java 对象类似。
分布式垃圾收集:
RMI 采用其分布式垃圾收集功能收集不再被网络中任何客户程序所引用的远程服务对象。分布式垃圾收集功能允许用户根据自己的需要定义服务器对象,
并且明确这些对象在不再被客户机引用时会被删除。
分布式对象模型
RMI 工作流程
当客户端通过RMI注册表找到一个远程接口的时候,所得到的其实是远程接口的一个动态代理对象。当客户端调用其中的方法的时候,方法的参数对象会在序列化之后,传输到服务器端。服务器端接收到之后,进行反序列化得到参数对象。并使用这些参数对象,在服务器端调用实际的方法。调用的返回值Java对象经过序列化之后,再发送回客户端。客户端再经过反序列化之后得到Java对象,返回给调用者。这中间的序列化过程对于使用者来说是透明的,由动态代理对象自动完成。除了序列化之外,RMI还使用了动态类加载技术。当需要进行反序列化的时候,如果该对象的类定义在当前JVM中没有找到,RMI会尝试从远端下载所需的类文件定义。可以在RMI程序启动的时候,通过JVM参数java.rmi.server.codebase来指定动态下载Java类文件的URL。
RMI应用包含两个独立的程序,服务器程序和客户端程序,服务器程序创建多个远程对象,使这些远程对象能够被引用,然后等待客户机调用这些远程对象的方法,客户机可以取到一个或者多个远程对象的引用。然后调用远程对象的方法。
A、定位远程对象
两种机制获取远程对象的引用,使用rmiregistry 来注册远程对象;也可以使用远程对象引用作为常规操作的一部分来传递和返回。
B、如何与远程对象通信
客户机在服务器注册程序中用远程对象的名字查找该远程对象,然后调用这个对象的方法。RMI能用java系统支持的任何URL协议(HTTP,FTP,file)加载字节码。
术语定义
远程对象(remote object):它的方法可以从其它java虚拟机上调用,该类型的对象由一种或者多种remote interfaces 描述。远程方法调用就是调用远程对象上远程接口的方法和动作。
分布式远程对象和java对象的不同
(1) 客户机和远程接口发生交互,而从不与这些接口的实现类发生交互。
(2) 远程方法的非远程参数和返回结果是通过复制而非引用的方式传递,因为对象引用只有在单虚拟机中才起作用。
(3) 远程对象以引用的方式传递
远程方法调用中的参数传递
传给远程对象的参数或源于它的返回值可以是任意可序列化的Java 对象。这包
括Java 基本类型, 远程Java对象和实现java.io.Serializable 接口的
非远程Java 对象。本地得不到的作为参数或返回值的类,可通过RMI 系统进行动态下载。
(1)、传递非远程对象
非远程对象将作为远程方法调用的参数传递或作为远程方法调用的结果返回时,
是通过复制传递的;也就是使用Java 对象序列化机制将该对象序列化。
从远程方法调用返回非远程对象时,将在调用的虚拟机中创建新对象。
(2)、传递远程对象
当将远程对象作为远程方法调用的参数或返回值传递时,远程对象的stub 程序
即被传递出去。作为参数传递的远程对象仅能实现远程接口。
类注解
当对象在远程调用中被从一个虚拟机发送到另一个虚拟机中时,RMI 系统在调用
流中用类的信息 (URL) 给类描述符加注解,以便该类能在接收器上加载。在远
程方法调用期间,调用可随时下载类。
引用的完整性
如果一个对象的两个引用在单个远程方法调用中以参数形式(或返回值形式)从
一个虚拟机传到另一个虚拟机中,并且它们在发送虚拟机中指向同一对象,则两
个引用在接收虚拟机中将指向该对象的同一副本。进一步说就是:在单个远程方
法调用中, RMI 系统将在作为调用参数或返回值传递的对象中保持引用的完整性
Java 分布式对象模型在以下几方面与Java 对象模型不同:
远程对象的客户机与远程接口发生交互,而从不与这些接口的实现类交互。
远程方法的非远程参数和返回结果是通过复制而非引用的方式传递的。这是因为
对象的引用只在单个虚拟机中才有用。也就是在调用的虚拟机中创建了一个新对象。
远程对象以引用的方式进行传递,而不是复制实际的远程实现。
定位远程对象
提供了一种简单的引导名字服务器,用于存储对远程对象的已命名引用。使用类 java.rmi.Naming 的基于 URL 的方法可以存储远程对象引用。客户机要调用远程对象的方法,则必须首先得到该对象的引用。对远程对象的引 用通常是在方法调用中以返回值的形式取得。RMI 系统提供一种简单的引导名字服务器,通过它得到给定主机上的远程对象。
Stub和Skeleton
远程对象的Stub 担当远程对象的客户的本地代表或代理人角色。调用程序将调用本地的Stub方法,而本地的Stub将负责执行对远程对象的方法调用在 RMI 中,远程对象的 stub 与该远程对象所实现的远程接口集相同。
初始化与包含远程对象的远程虚拟机的连接。
调用 stub 的方法时,将执行下列操作:
(1)、对远程虚拟机参数的进行编组(写入并传输)
(2)、等待方法调用结果
(3)、解编(读取)返回值或返回的异常
(4)、将值返给调用程序
在远程虚拟机中,每个远程对象都可以有相应的 skeleton。skeleton 负责将调用分配给实际的远程对象实现。
skeleton它在 接收入进入方法调用时执行下列操作:
(1)、解编(读取)远程方法的参数
(2)、调用实际远程对象实现上的方法
(3)、将结果(返回值或异常)编组(写入并传输)给调用程序
动态类加载
java.rmi.server 类 RMIClassLoader
RMI 允许传入 RMI 调用中的参数、返回值和异常为任何可序列化对象。 RMI 使
用对象序列化机制将数据从一个虚拟机传输到另一个虚拟机,同时用相应的位置 (URL)
信息注释调用流,以便在接收端上加载类定义文件。
1)一个实例通过线路发送。作为一部分对象序列化信息,所有类定义相关的信息被通过线路发送。每一个类还有URL的字符串序列。
2)反序列化机制为刚描述的类寻找合适的ClassLoader。之所以可以这样是因为,RMI运行时保持了一个URLCassLoader实例集合的索引。
3)如果类存在,URLClassLoader的实例就返回他们。如果类不存在则URLClassLoader下载他们。
因为ClassLoader类在试图下载他们之前先向其父节点请求,第一个试图下载的会从文件系统下载。如果引导ClassLoader不能下载类,则类下载仅仅使用URLs。
客户端接口
Java.rmi.Remote 接口用来识别所有远程接口;所有远程对象必须直接或者间接实现此接口。
Java.rmi.RemoteException 是许多在执行远程方法调用时可能发生的与通信有关的异常超类。
Java.rmi.Naming 提供存储和获取远程对象注册服务程序中远程对象进行引用的方法。
Naming类中的方法以如下形式的,URL格式的java.lang.String 作为其中的一个参数:
//host:port/name
其中host是注册服务程序所在的主机(远程或者本地),port 是注册服务程序接收调用的端口号,host 如果省略则缺省值是本地主机,如果省略port,则端口缺省值是1099,即RMI系统注册服务器程序rmiregistry所用的端口。
为远程对象绑定名称,可以查询该远程对象,Naming类中的bind 或者rebind 方法将远程对象和名称关联。远程对象和名称绑定后(注册),远程主机上的调用程序就可以按名称查询远程对象、获取其引用,然后在对象上调用远程方法。Lookup 方法返回与文件部分相关联的远程对象,如果名称未绑定到远程对象上,则抛出NotBoundException。
服务器接口
Java.rmi.server 包包含通常用于实现远程对象的接口和类。
RemoteObject
实现与远程对象。实现方法hashCode 和equals 将允许将远程对象引用存储在散列表中进行比较。如果两个Remote 对象引用同一个远程对象,则方法equals 返回true。负责比较远程对象的远程对象引用。
WriteObject 和readObject 它们由对象序列化机制调用来处理向java.io.ObjectOutputStream 中序列化数据。RemoteObject 的序列化形式由下列方法写入:
WriteObject(java.io.ObjectOutputStream out)
RemoteServer
Java.rmi.server.RemoteServer是服务器实现类,extends RemoteObject。
两个具体的子类java.rmi.server.UnicastRemoteObject 和java.rmi.activation.Activatable。
RMISecurityManager
RMISecurityManager 提供与java.lang.SecurityManager相同安全特性,但它覆盖了checkPackageAccess方法。在RMI应用程序中,如果没有设置安全管理器,则只能从本地类路径下载stub 和类。
RMIClassLoader
RMIClassLoader 类提供一套静态方法,用于支持RMI中基于网络的类加载。
RMI 套接字工厂
Stub 和skeleton编译器
本文章转自 http://blog.csdn.net/cdl2008sky/article/details/6844719;