JAVA RMI 文档中文(二)

2.6 远端方法调用时的参数传递

一个远端对象只要可以序列化就可以是方法参数或是返回值。这就包括了基础对象、远端对象和实现了java.io.Serializable的非远端对象。更多关于如何序列化类的信息科一参考 “Java Object Serialization Specification”。这些参数或者返回值不是本地的,它们是通过RMI系统动态下载的。更多细节查看Dynamic Class Loading

2.6.1 传递非远端对象

一个非远端对象,无论是作为参数还是返回值,它都是通过复制来传递的,也就是通过java的序列化机制序列化后得到的。

所以,在方法调用过程中,当一个远端对象作为参数或者返回值被传递时,这个非远端对象的内容会在方法调用前被复制。

当调用远端方法返回一个非远端对象时,本地虚拟机就会创建一个新的对象。

2.6.2 传递远端对象

当传递一个远端对象时,实际传递的是这个对象的存根(stub)。
没有暴露的远端对象不会被存根实例替代。远端对象只有实现了远端接口才可以作为参数被传递。

2.6.3 引用的完整性(Referential Integrity)

如果一个对象的两个引用作为一个远端方法的参数从一个虚拟机传递到另一个虚拟机,那么这些引用在发送对象的虚拟机中指向的是同一个对象,它们在接收对象的虚拟机中指向的是同一个对象的副本,RMI系统会在对象传递过程中保证引用的完整性。

2.6.4 类注释(Class Annotation)

当一个对象通过方法调用,从一个虚拟机传递到另一个虚拟机时,RMI系统会通过URL来标识这个类,以便可以在接收端加载这个类。这个要求保证类会按需下载。
(这里翻译的感觉有点问题,下面是原文)

When an object is sent from one JVM to another in a remote method call, the RMI system annotates the class descriptor in the call stream with information (the URL) of the class so that the class can be loaded at the receiver. It is a requirement that classes be downloaded on demand during remote method invocation.

2.6.5 参数传递

在RMI调用中参数被写到流中,该流是java.io.ObjectOutputStream的子类,这样是为了可以将参数序列化到远端调用虚拟机中。ObjectOutputStream子类会重写replaceObject方法,该方法用每一个暴露的远端对象所对应的存根实例来替换他们。参数这些对象是通过ObjectOutputStreamwriteObject方法来写入流中的。ObjectOutputStream会为每一个通过writeObject方法写入流的对象调用replaceObject方法(包括写入对象所引用的对象)。replaceObject方法返回结果如下:
1、如果这个对象实现了java.rmi.Remote而且这个对象在RMI运行时被导出,那么该方法返回这个对象的存根实例。如果这个对象实现了java.rmi.Remote,但是没有在RMI运行时被导出,那么replaceObject方法返回该对象本身。对于远端对象的存根,可以通过调用java.rmi.server.RemoteObjecttoStub方法获得。
2、如果这个对象不是一个java.rmi.Remote的实例,那么会简单返回该对象。

RMI中ObjectOutputStream的子类也会实现annotateClass方法,该类会通过远端类的位置来对类进行解释说明,以便该类可以在接收端被下载。

因为参数写入是通过一个单独的ObjectOutputStream,所以同一个对象的引用在接收端会指向同一个对象的副本。在接收端,参数通过一个单独的ObjectInputStream读出来。

ObjectOutputStream的其他任何写对象的行为(ObjectInputStream的读取对象和它类似)都是在参数传递中维护的。比如说,在写对象是会调用writeReplace方法,在读对象的时候回调用readResolve方法,这些方法都是由RMI参数的编排或者反编排流提供的。

返回值和异常的传递和上面讲的参数传递类似。

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 1
    评论
web报表工具 请移步:http://download.csdn.net/source/2881508 不多说,除了RMI的学习外,gui对新手入门也是个不错的学习 /* *此类适合在本地注册的RMI服务器,避免了使用了多个DOS的写法,只需要简单的给使用 *本类提供的方法即可。 */ package common.rmiserver; import java.rmi.Naming; import java.rmi.NotBoundException; import java.rmi.Remote; import java.rmi.registry.Registry; import java.rmi.registry.LocateRegistry; //import java.rmi.RMISecurityManager; import java.rmi.RemoteException; import java.net.MalformedURLException; import java.rmi.server.UnicastRemoteObject; import common.zip.ZipClientSocketFactory; import common.zip.ZipServerSocketFactory; public final class RMIServer { private Registry registry = null; // @jve:decl-index=0: private String serverName = "RMIServer"; private String serverPath = "localhost"; private int port = 1099; private Remote serverInterface = null; private Boolean isStart = false; private AllFace dataAllFace = null; private int dataPort = 0;// 数据端口,0表示端口由RMI服务器动态生成. private Remote stub; public RMIServer() { } /* * 使用默认端口,默认服务器名称,服务路径构造函数 use the default port,server name and the url */ public RMIServer(Remote obj) { this.serverInterface = obj; } /* * 使用默认端口,服务路径构造函数 use the default port and server url */ public RMIServer(String servername, Remote obj) { this.serverName = servername; this.serverInterface = obj; } /* * 服务器为默认值的构造函数 use the default url */ public RMIServer(String servername, int port, Remote obj) { this.port = port; this.serverName = servername; this.serverInterface = obj; } /* * 适合1.4范围的版本,当然也适合5.0的版本 */ public Boolean setStart() throws RemoteException, MalformedURLException, NotImplementInterfaceException { if (registry == null) registry = LocateRegistry.createRegistry(port); if (serverInterface == null) { throw new NotImplementInterfaceException( "not found the reote interface method!!"); } Naming.rebind("rmi://"+serverPath + ":" + port + "/" + serverName, serverInterface); isStart = true; return isStart; } /* * jdk5.0以后的写法,在使用之前使用setXxx方法给对象赋值 */ public Boolean start() throws RemoteException, MalformedURLException, NotImplementInterfaceException { if(stub==null) stub = (Remote) UnicastRemoteObject.exportObject(dataAllFace, dataPort);// 0表示端口随机生成. if (registry == null) registry = LocateRegistry.createRegistry(port, new ZipClientSocketFactory(), new ZipServerSocketFactory()); setProperty(serverPath); //绑定IP registry.rebind(serverName, stub); isStart = true; return isStart; } /* * 如果有多个ip,则使用这个方法绑定指定的IP */ public void setProperty(String ip) { System.setProperty("java.rmi.server.hostname", ip); } /* * close the server */ public void close() throws RemoteException, MalformedURLException, NotBoundException { //UnicastRemoteObject.unexportObject(dataAllFace, true); Naming.unbind("rmi://"+serverPath + ":" + port + "/" + serverName); isStart = false; } /* * set server name,if not set the name,the service will use the default name * "RMIServer" */ public void setServerName(String serverName) { this.serverName = serverName; } /* * set the server URL,default localhost "rmi://localhost" */ public void setServerPath(String serverPath) { this.serverPath = serverPath; } /* * set the server port default port is 1099. */ public void setPort(int port) { this.port = port; } /* * set then remote implement method */ public void setServerInterface(Remote serverInterface) { this.serverInterface = serverInterface; } /* * set the server Security */ public void setSecurityManager() { /* if (System.getSecurityManager() == null) { try { // java -Djava.security.policy=policy.txt // common.rmiserver.RMIServer System.setSecurityManager(new RMISecurityManager());// 暂时不要安全设置, } catch (java.rmi.RMISecurityException exc) { throw exc; } }*/ } /* * set the remote method */ public void setDataAllFace(AllFace dataAllFace) { this.dataAllFace = dataAllFace; } /* * set the remote dataport */ public void setDataPort(int dataPort) { this.dataPort = dataPort; } // ----------------------------------------------- /* * return the server URL */ public String getServerPatth() { return serverPath; } /* * return remote method */ public Remote getserverInterface() { return serverInterface; } /* * return the server name */ public String getServerName() { return serverName; } /* * return the server use port */ public int getPort() { return port; } /* * return the server then action state */ public Boolean isStart() { return isStart; } /* * return remote method */ public AllFace getDataAllFace() { return dataAllFace; } /* * return remote dataport */ public int getDataPort() { return dataPort; } }
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值