`
gyabooks
  • 浏览: 23783 次
  • 性别: Icon_minigender_1
  • 来自: 北京
社区版块
存档分类
最新评论

RMI(Remote Method Invocation)原理浅析

阅读更多

博采众生现代的 网络和编程技术,让我们的资源共享从信息逐步迈向了硬件,你想到过吗?你可以把一个解密的任务放到远程的运行更快的,闲置的服务器上进行,最后把运算的结果返回来,你 所要做的就是提交任务。看到了吧,处理这些任务是远程的服务器。

Java的RMI的技术让这种实现变得非常的容易,本文就从基础性的东西讲解一下RMI的原理,有关安全和部署的问题,本文不加于讨论。 读过本文希望对你的学习有所帮助。

声明:未经允许,请勿转载本文,谢谢!

本文将讨论以下内容:

一、RMI的定义

1、RMI定义和功能

RMI是Remote Method Invocation的简称,是J2SE的一部分,能够让程序员开发出基于Java的分布式应用。一个RMI对象是一个远 程Java对象,可以从另一个Java虚拟机上(甚至跨过网络)调用它的方法,可以像调用本地Java对象的方法一样调用远程对象的方法,使分布在不同的JVM中的对象的外表和行为都 像本地对象一样。

2、Stub和Skeleton介绍

在学习RMI的时,我们不能不讨论stub和skeleton作用和相关问题。他们是我们理解RMI原理的关键。我做个比方说明这两个概念。 假如你是A,你想借D的工具,但是又不认识D的管家C,所以你找来B来帮你,B认识C。B在这时就是一个代理,代理你的请求,依靠自己的话语去借。C呢他负责D家东西收回和借出 ,但是要有D的批准。在得到D的批准以后,C再把东西给B,B呢再转给A。stub和skeleton在RMI中就是角色就是B和C,他们都是代理角色,在现实开发中隐藏系统和网络的的差异, 这一部分的功能在RMI开发中对程序员是透明的。Stub为客户端编码远程命令并把他们发送到服务器。而Skeleton则是把远程命令解码,调用服务端的远程对象的方法,把结果在编 码发给stub,然后stub再解码返回调用结果给客户端。所有的操作如下图所示:

博采众生

二、RMI原理的浅析

1、RMI的应用开发流程

为了方便理解,在这里我先介绍RMI应用开发的流程。如果你在网上搜索RMI,你会看到好多有关RMI的经典例子。在这里需要说明的就是 从JDK5.0以后,stubs和skeleton的类的产生不需要使用单独的rmic编译器了,所以本文开发流程就简化为客户端和服务端,没有中间的stub和skeleton的环节。整个开发流程如下 图:

博采众生

公共接口是客户端和服务端共同存在的,定义了远程对象将要实现的功能,客户端依这个接口调用的方法,在服务端都必须实现。随后 我们要开发实现接口的,继承java.rmi.UnicastRemoteObject的实现类,暂且把其称为Impl,这个类我们将在随后的服务端类中实例化并把其注册到RMI注册表中。运行RMI注册表 服务,具体各个平台的启动方法,请你参考JDK文档。而余下的问题就是开发服务端类和客户端类了,在服务类中,需要实例化Impl,并用一个字符串把这个对象绑定到RMI注册表 中;客户端需要实现检索RMI注册表获得需要远程对象的stub,进行远程方法调用。关于如何的实现,请网友看本文的RMI简单实现部分。

2、Stub和Skeleton在什么位置产生

网上有太多的stub和skeleton的疑问了,对stub和skeleton迷惑影响了对RMI的学习。从JDK5.0以后,这两个类就不需要rmic来产生了 ,而是有JVM自动处理,实际上他们还是存在的。Stub存在于客户端,作为客户端的代理,让我们总是认为客户端产生了stub,接口没有作用。实际上stub类是通过Java动态类下载 机制下载的(具体内容请参考:Java RMI实现代码动态下载),它是由服 务端产生,然后根据需要动态的加载到客户端,如果下次再运行这个客户端该存根类存在于classpath中,它就不需要再下载了,而是直接加载。(具体的内部细节,需要参考Sun 的Rmi - Java Remote Method Invocation – Specification)。总的来说,stub是在服务端产生的,如果服务端的stub内容改变,那么客户端的也是需要同步更新。

3、Stub和公共接口interface(远程对象的功能)的关系

我的一篇译文上,一个网友说 “如果客户端有接口的话,我还要那个存根来干什么??直接用接口不就完事了?经过测试,客户端放一个接口的话,根本不需要存根,这个是我一直想不明白的..........”。在开始 学习时,我也是有这个疑问,通过接口直接调用不就OK了吗?实际上,存根是我们必需的。一个服务如果没有合适的存根类,客户就没有办法去调用远程的接口,RMI使用存根来返 回引用远程对象接口的参数。在类的关系中,接口是不能实例化的,但是它可以指向一个实现该接口的实例。存根和接口就是这种关系,而存根类的实例就是在:lookup ()方法 调用时加载、实例的。接口只是告诉JVM,内存中这片的字节码中,这几个方法我可以调用。

4、rmiregistry介绍

我们用一个图示来说明rmiregistry的作用:

博采众生

Rmiregistry需要在提供远程对象服务端启动,它提供了一个环境,说白了就是在内存中,开辟了一片空间,用来接受服务端服务程序的 注册,产生一个类似于数据库,提供存储检索远程对象功能的注册表。这个RMI注册表,就是我们常听到的RMI名字服务。远程客户端,就是依靠它获得存根,调用远程方法。说到 这里有一个端口的问题,如果你在启动rmiregistry时,设定了非默认端口,那么需要在服务端和客户端统一使用该端口,否则就会有RemoteException的异常抛出,rmiregistry提 供的服务是针对特定的端口号的,不然在同一台机器上也是无法提供服务。

到此,有关RMI的原理的东西,就简单地介绍了,如果你还有什么疑问,请你留言,接下来我们来进行一个实例,复杂一些的实例(含带 UI),我在下一篇文章中介绍。

三、RMI简单实现

首先,我的环境:Windows XP,JDK1.6。所以我在这个实例中不再使用rmic编译stub和skeleton了。要实现的就是两个部分:客户端和 服务端。我们使用经典的Hello,world!例子。

文件清单如下:

  • 接 口:MyRmiInterface.java
  • 客户端:MyRmiClient.java
  • 服务端:MyRmiImpl.java(实现类) MyRmiServer.java
  • 你可以采用两台电脑,也可以一台,但是MyRmiInterface.class和MyRmiClient.class存在于客户端,MyRmiInterface.class, MyRmiImpl.class与MyRmiServer.class存在服务端。所有程序代码清单如下:

    客户端:

    1. package net.csdn.blog.qb2049.exam;
    2. //MyRmiInterface.java
    3. import java.rmi.*;
    4. //这个接口必需继承Remote 接口
    5. public interface MyRmiInterface extends Remote
    6. {
    7. //声明方法 时,必需显式地抛出RemoteException异常
    8. public String sayHello() throws RemoteException;
    9. }
    *************************************************************
    1. package net.csdn.blog.qb2049.exam;
    2. import java.rmi.*;
    3. import java.rmi.registry.*;
    4. //MyRmiClient.java
    5. public class MyRmiClient
    6. {
    7. public MyRmiClient(){}
    8. public static void main(String args[])
    9. {
    10. String host=(args.length<1)?null:args [0];
    11. try{
    12. //获得运行rmiregistry服务的主机上的注 册表
    13. Registry registry=LocateRegistry.getRegistry(host);
    14. //查询并获得远程对象的存根
    15. MyRmiInterface stub=(MyRmiInterface) registry.lookup("Hello");
    16. //像在使用本地对象方法那样,调用远程方法
    17. String response=stub.sayHello();
    18. System.out.println("response:"+response);
    19. }catch(Exception e)
    20. {
    21. System.out.println("Client exception :"+ e.toString());
    22. e.printStackTrace();
    23. }
    24. }
    25. }

    服务端:(服务端也是需要存在接口)

    1. package net.csdn.blog.qb2049.exam;
    2. import java.rmi.*;
    3. import java.rmi.server.*;
    4. //这个类继承 UnicastRemoteObject非常重要
    5. //MyRmiImpl.java
    6. public class MyRmiImpl extends UnicastRemoteObject implements MyRmiInterface
    7. {
    8. //在实例化这个类时,就导出了远程对象,该构造方法必需
    9. public MyRmiImpl() throws RemoteException
    10. {
    11. super();
    12. }
    13. //实现接口中的方法,这个时间不需要显 式抛出RemoteException异常了
    14. public String sayHello()
    15. {
    16. return "Hello ,world";
    17. }
    18. }
    *************************************************************
    1. package net.csdn.blog.qb2049.exam;
    2. import java.rmi.*;
    3. import java.rmi.registry.*;
    4. import java.rmi.server.*;
    5. //MyRmiServer.java
    6. public class MyRmiServer
    7. {
    8. public static void main(String args[])
    9. {
    10. try{
    11. //实例化远程对象,同时导出了该对象
    12. MyRmiImpl server=new MyRmiImpl ();
    13. //获得本地RMI注册表对象
    14. Registry registry=LocateRegistry.getRegistry();
    15. //在注册表中绑定远程对象
    16. registry.bind("Hello",server);
    17. //通告服务端已准备好了
    18. System.out.println("System already!");
    19. }catch(RemoteException e)
    20. {
    21. System.out.println("在建立远程连接的情况出现了异 常"+e.getMessage());
    22. System.out.println(e.toString());
    23. } catch(AlreadyBoundException e1){
    24. System.out.println("在向注册表 中绑定时出现了问题,名字已被绑定了!
    25. \n"+e1.getMessage());
    26. }
    27. }
    28. }
    *************************************************************

    实验环境目录如下图示:

    博采众生

    编译服务端

    博采众生

    编译客户端

    博采众生

    启动注册表环境,它没有任何输出

    博采众生

    启动服务端,提示ready!

    博采众生

    启动客户端端,得到Hello World!

    博采众生

    编译中可能出现的问题

    启动中,可能由于codebase设置出现问题,总是抛出ClassNotFoundException异常,使你的服务器程序无法启动,建议你参考Java RMI实现代码动态下载来寻求帮助!

    本文参考:

  • 1、Java与CORBA 客户/服务器编程(第二版)亢勇等译电子工业出版社
  • 2、Sun公司JDK文档
  • 3、Understanding Java RMI Internals Ahamed Aslam.K Develper.com
  • 4、Java2 核心技术卷II王浩、姚建平等译机械工业出版社
  • 5、Java远程方法调用(Remote Method Invocation, RMI)http://www.blogjava.net/yruc/
  • alimama_pid="mm_11642003_1480608_3725409"; alimama_titlecolor="0000FF"; alimama_descolor ="000000"; alimama_bgcolor="FFFFFF"; alimama_bordercolor="E6E6E6"; alimama_linkcolor="008000"; alimama_bottomcolor="FFFFFF"; alimama_anglesize="0"; alimama_bgpic="0"; alimama_icon="0"; alimama_sizecode="11"; alimama_width=760; alimama_height=90; alimama_type=2;
    分享到:
    评论

    相关推荐

      RMI代码 remote method invocation

      远程方法调用(Remote Method Invocation,RMI)是Java平台中一种用于分布式计算的技术,它允许Java对象在不同的 JVM(Java虚拟机)之间调用方法,仿佛这些对象都在同一个JVM中一样。RMI是Java EE(现在被称为...

      Remote Method Invocation-远程方法调用

      ### Remote Method Invocation (RMI) – 远程方法调用详解 #### 一、RMI 概述 **远程方法调用**(Remote Method Invocation, RMI)是Java平台中的一个核心概念和技术,它允许开发者创建分布式应用,在这些应用中,...

      JDK10-JSE,Java Remote Method Invocation API Guide-2.pdf

      Java Remote Method Invocation(Java RMI)是一种允许分布式应用程序在Java平台上运行的技术。它允许在不同的Java虚拟机(JVM)上运行的对象之间调用方法,从而实现分布式计算和信息-sharing。 Java RMI使用对象...

      JDK9-JSE- Java Remote Method Invocation API Guide-2.pdf

      Java Remote Method Invocation(Java RMI)是一种允许开发者创建分布式应用程序的技术。Java RMI 允许对象在另一个 Java 虚拟机(JVM)上调用远程 Java 对象的方法,可能在不同的主机上。Java RMI 使用对象序列化来...

      Java RMI(Remote Method Invocation)远程方法调用 详解

      Remote Method Invocation是一种机制,能够让在某个 Java 虚拟机上的对象调用另一个 Java 虚拟机中的对象上的方法。 编写一个RMI的步骤 定义一个远程接口,此接口需要继承java.rmi.Remote 开发远程接口的实现类 创建...

      RMI 简单示例-Java Remote Methods Invocation

      Java Remote Method Invocation(RMI)是Java平台提供的一种用于在分布式环境中进行对象间通信的技术。RMI允许一个Java对象在某台计算机上执行其方法,而这个对象实际上存在于另一台计算机上。这种技术使得开发者...

      jdk20-java-remote-method-invocation-api-guide.pdf

      Java Platform, Standard Edition 的 Java Remote Method Invocation API Guide 介绍了 Java Remote Method Invocation(Java RMI)的概念和应用。Java RMI 是一种分布式应用程序开发技术,允许对象在不同的 Java ...

      JDK19-java-remote-method-invocation-api-guide.pdf

      Java Platform, Standard Edition 的 Java Remote Method Invocation (Java RMI) 是一种允许创建分布式应用程序的技术。Java RMI 允许对象在另一个 Java Virtual Machine (JVM) 上的远程 Java 对象上调用方法,可能...

      JDK15-java-remote-method-invocation-api-guide.pdf

      Java Remote Method Invocation(Java RMI)是 Java 平台提供的一种分布式应用程序开发技术,允许对象在不同的 Java 虚拟机(JVM)上调用远程 Java 对象的方法。RMI 使用对象序列化来 marshal 和 unmarshal 参数,...

      JDK16-java-remote-method-invocation-api-guide.pdf

      Java Platform, Standard Edition 的 Java Remote Method Invocation(Java RMI)允许您创建分布式应用程序。Java RMI 允许对象在另一个 Java Virtual Machine(JVM)上调用远程 Java 对象的方法,可能位于不同的...

      JDK18-java-remote-method-invocation-api-guide.pdf

      Java RMI(Java Remote Method Invocation,Java 远程方法调用)是一种允许 Java 对象在不同的 Java 虚拟机(JVM)上进行方法调用的一种机制。RMI 使用对象序列化来 marshal 和 unmarshal 参数,并且支持真正的面向...

      JDK12-java-remote-method-invocation-api-guide.pdf

      Java Remote Method Invocation(Java RMI)是一种允许对象在远程Java虚拟机(JVM)上调用方法的技术。RMI使用对象序列化来 marshal 和 unmarshal 参数,不会截断类型,支持真正的面向对象的多态性。然而,RMI应用...

      JDK13-java-remote-method-invocation-api-guide.pdf

      Java Remote Method Invocation (Java RMI) 是Java平台标准版(Java SE)中的一部分,它允许对象在不同的Java虚拟机(JVM)之间进行远程方法调用,这些JVM可能运行在不同的主机上。RMI利用Java的对象序列化机制来...

      RMI.zip_remote

      在Java编程领域,远程方法调用(Remote Method Invocation,RMI)是一种强大的技术,它允许在不同的Java虚拟机(JVM)之间透明地调用对象的方法。标题"RMI.zip_remote"表明这是一个与RMI相关的代码示例压缩包,而...

      RMI-remote-file-transfer.rar_remote_rmi file transfer

      Java RMI(Remote Method Invocation,远程方法调用)是一种在分布式环境中进行对象间通信的技术,它允许一个Java对象调用另一个在不同 JVM(Java虚拟机)上的对象的方法。在这个"RMI-remote-file-transfer.rar"项目...

      JavaBean和RMI 学习

      Java RMI(Remote Method Invocation)--Java的远程方法调用是Java所特有的分布式计算技术,它允许运行在一个Java虚拟机上的对象调用运行在另一个Java虚拟机上的对象的方法,从而使Java编程人员可以方便地在网络环境...

      rmi.rar_remote

      远程方法调用(Remote Method Invocation,RMI)是Java编程语言中的一项重要技术,它允许在不同的Java虚拟机(JVM)之间进行分布式计算。在Java RMI中,一个对象可以调用另一个位于不同网络位置的对象的方法,就像...

      RMI.rar_remote_分布式 通信

      Java远程方法调用,即Java RMI(Java Remote Method Invocation)是Java编程语言里,一种用于实现远程过程调用的应用程序编程接口。它使客户机上运行的程序可以调用远程服务器上的对象。远程方法调用特性使Java编程...

    Global site tag (gtag.js) - Google Analytics