`
kleu10kleu
  • 浏览: 14060 次
最近访客 更多访客>>
社区版块
存档分类
最新评论

JAVA RMI线程模型及内部实现机制

 
阅读更多

JAVA RMI线程模型及内部实现机制
2010年06月07日
  JAVA RMI是JAVA分布式结构的基础。远程对象的通信过程中,RMI使用标准机制:stub和skeleton。远程对象的stub担当远程对象的客户本地代表或代理人角色,调用程序将调用本地stub的方法,而本地stub将负责执行对远程对象的方法调用。在RMI中,远程对象的stub与该远程对象所实现的远程接口集相同。调用stub的方法时将执行下列操作:
  (1) 初始化与包含远程对象的远程虚拟机的连接;
  (2) 对远程虚拟机的参数进行编组-传输参数;
  (3) 等待远程方法调用结果;
  (4) 解编(读取)返回值或返回的异常;
  (5) 将值返回给调用程序。
  为了向调用程序展示比较简单的调用机制,stub将参数的序列化和网络级通信等细节隐藏了起来。在远程虚拟机中,每个远程对象都可以有相应的skeleton。skeleton负责将调用分配给实际的远程对象实现。它在接收方法调用时执行下列操作:
  (1) 解编(读取)远程方法的参数;
  (2) 调用实际远程对象实现上的方法;
  (3) 将结果(返回值或异常)编组(写入并传输)给调用程序。  
  stub和skeleton由rmic编译器生成。在最新的JDK中,不需要手工生产stub和skeleton,用动态代理生成的Proxy代替了stub,而skeleton则取消了。
  我们可以查看源代码来了解RMI的内部实现。Server端调用UnicastRemoteObject的export方法输出远程对象,export方法会在一个线程里监听某个TCP端口上的方法调用请求:  public void exportObject(Target target) throws RemoteException { // other code while (true) { ServerSocket myServer = server; if (myServer == null) return; Throwable acceptFailure = null; final Socket socket; try { socket = myServer.accept(); /* * Find client host name (or "0.0.0.0" if unknown) */ InetAddress clientAddr = socket.getInetAddress(); String clientHost = (clientAddr != null ? clientAddr.getHostAddress() : "0.0.0.0"); /* * Spawn non-system thread to handle the connection */ Thread t = (Thread) java.security.AccessController.doPrivileged ( new NewThreadAction(new ConnectionHandler(socket, clientHost), "TCP Connection(" + ++ threadNum + ")-" + clientHost, true, true)); t.start(); } catch (IOException e) { acceptFailure = e; } catch (RuntimeException e) { acceptFailure = e; } catch (Error e) { acceptFailure = e; } } // other code }   上面的代码已被修改以展示主要的要点,Server端就是在ServerSocket的accept方法上面监听到来的请求,如果有新的方法调用请求到来,Server产生一个单独的线程来处理新接收的请求:  public void dispatch(Remote obj, RemoteCall call) throws IOException { // positive operation number in 1.1 stubs; // negative version number in 1.2 stubs and beyond... int num; long op; try { // read remote call header ObjectInput in; try { in = call.getInputStream(); num = in.readInt(); if (num >= 0) { if (skel != null) { oldDispatch(obj, call, num); return; } else { throw new UnmarshalException( "skeleton class not found but required " + "for client version"); } } op = in.readLong(); } catch (Exception readEx) { throw new UnmarshalException("error unmarshalling call header", readEx); } /* * Since only system classes (with null class loaders) will be on * the execution stack during parameter unmarshalling for the 1.2 * stub protocol, tell the MarshalInputStream not to bother trying * to resolve classes using its superclasses's default method of * consulting the first non-null class loader on the stack. */ MarshalInputStream marshalStream = (MarshalInputStream) in; marshalStream.skipDefaultResolveClass(); Method method = (Method) hashToMethod_Map.get(new Long(op)); if (method == null) { throw new UnmarshalException("invalid method hash"); } // if calls are being logged, write out object id and operation logCall(obj, method); // unmarshal parameters Class[] types = method.getParameterTypes(); Object[] params = new Object[types.length]; try { unmarshalCustomCallData(in); for (int i = 0; i 结果写入到输出流中:marshalValue(rtype, result, out)。一个方法调用就执行完成了。
  Client端请求一个远程方法调用时,先建立连接:Connection conn = ref.getChannel().newConnection(),然后发送方法参数: marshalValue(types[i], params[i], out),再发送执行方法请求:call.executeCall(),最后得到方法的执行结果:Object returnValue = unmarshalValue(rtype, in),并关闭接:
  ref.getChannel().free(conn, true)。  public Object invoke(Remote obj, java.lang.reflect.Method method, Object[] params, long opnum) throws Exception { if (clientRefLog.isLoggable(Log.VERBOSE)) { clientRefLog.log(Log.VERBOSE, "method: " + method); } if (clientCallLog.isLoggable(Log.VERBOSE)) { logClientCall(obj, method); } Connection conn = ref.getChannel().newConnection(); RemoteCall call = null; boolean reuse = true; /* If the call connection is "reused" early, remember not to * reuse again. */ boolean alreadyFreed = false; try { if (clientRefLog.isLoggable(Log.VERBOSE)) { clientRefLog.log(Log.VERBOSE, "opnum = " + opnum); } // create call context call = new StreamRemoteCall(conn, ref.getObjID(), -1, opnum); // marshal parameters try { ObjectOutput out = call.getOutputStream(); marshalCustomCallData(out); Class[] types = method.getParameterTypes(); for (int i = 0; i socket, clientHost), "TCP Connection(" + ++ threadNum + ")-" + clientHost, true, true));   在JDK1.6之后,RMI使用线程池来处理新接收的远程方法调用请求-ThreadPoolExecutor。
  下面是一个简单的RMI程序的执行线程抓图,我们可以更好的了解RMI的线程机制。这个简单的RMI程序是服务端有一个远程方法实现,一个客户端同时请求执行这个远程方法100次。在JDK1.5中执行时生成的线程如下图所示,每个方法调用请求都是在一个单独的线程里执行,即 A Thread per Request。
  
  在JDK1.6中执行时生成的线程如下图所示,这些线程都是在ThreadPoolExecutor线程池中执行的。
  
  在JDK1.6中,RMI提供了可配置的线程池参数属性:
  sun.rmi.transport.tcp.maxConnectionThread - 线程池中的最大线程数量
  sun.rmi.transport.tcp.threadKeepAliveTime - 线程池中空闲的线程存活时间
分享到:
评论

相关推荐

    JAVA_API1.6文档(中文)

    java.util 包含 collection 框架、遗留的 collection 类、事件模型、日期和时间设施、国际化和各种实用工具类(字符串标记生成器、随机数生成器和位数组)。 java.util.concurrent 在并发编程中很常用的实用工具类...

    Java清华教程.rar

    Java语言的发展及相关技术的介绍,Java技术和平台在网络计算及电子商务中的应用介绍;  ■ Java语言的基础知识:Java语言的主要特点,设计思想,Java虚拟机,垃圾回收机制,安全性的保证机制;  ■ Java语言的...

    socket通讯汇总

    用Java实现一个UDP通信模型 pdf 用Java实现一个Socket通信模型 pdf 用Java实现网络通讯 pdf 用JAVA实现基于TCP的SOCKET编程 pdf 用Java实现基于TCPIP协议的网络通信程序 pdf 一种基于JAVA多线程的即时显示策略 ...

    Java 1.6 API 中文 New

    java.util 包含 collection 框架、遗留的 collection 类、事件模型、日期和时间设施、国际化和各种实用工具类(字符串标记生成器、随机数生成器和位数组)。 java.util.concurrent 在并发编程中很常用的实用工具类。...

    清华大学java教程

    ■ Java语言的发展及相关技术的介绍,Java技术和平台在网络计算及电子商务中的应用介绍;  ■ Java语言的基础知识:Java语言的主要特点,设计思想,Java虚拟机,垃圾回收机制,安全性的保证机制;  ■ Java语言...

    JAVA清华教程 详细

    java清华版教程, ■ Java语言的发展及相关技术的介绍,Java技术和平台在网络计算及电子商务中的应用介绍;  ■ Java语言的基础知识:Java语言的主要特点,设计思想,Java虚拟机,垃圾回收机制,安全性的保证机制...

    java api最新7.0

    java.util 包含 collection 框架、遗留的 collection 类、事件模型、日期和时间设施、国际化和各种实用工具类(字符串标记生成器、随机数生成器和位数组)。 java.util.concurrent 在并发编程中很常用的实用工具类。...

    JavaAPI1.6中文chm文档 part1

    java.awt.datatransfer 提供在应用程序之间和在应用程序内部传输数据的接口和类。 java.awt.dnd Drag 和 Drop 是一种直接操作动作,在许多图形用户界面系统中都会遇到它,它提供了一种机制,能够在两个与 GUI 中...

    [清华大学]JAVA教程

     ■ Java语言的发展及相关技术的介绍,Java技术和平台在网络计算及电子商务中的应用介绍;  ■ Java语言的基础知识:Java语言的主要特点,设计思想,Java虚拟机,垃圾回收机制,安全性的保证机制;  ■ Java...

    JavaAPI中文chm文档 part2

    java.awt.datatransfer 提供在应用程序之间和在应用程序内部传输数据的接口和类。 java.awt.dnd Drag 和 Drop 是一种直接操作动作,在许多图形用户界面系统中都会遇到它,它提供了一种机制,能够在两个与 GUI 中...

    socket通讯资料汇总

    用Java实现一个UDP通信模型.pdf 用Java实现一个Socket通信模型.pdf 用Java实现网络通讯.pdf 用JAVA实现基于TCP的SOCKET编程.pdf 用Java实现基于TCPIP协议的网络通信程序.pdf 一种基于JAVA多线程的即时显示策略....

    JAVA清华大学教程

    ★ 第六讲 Java的线程和Java Applet ◇课前索引 ◇6.1 线程简介 ◇6.2 多线程的互斥与同步 ◇6.3 Java Applet ◇本讲小结 ◇课后习题 ★ 第七讲 Swing用户界面设计 ◇课前索引 ◇7.1 Swing简介 ◇7.2 ...

    java jdk-api-1.6 中文 chmd

    java.awt.datatransfer 提供在应用程序之间和在应用程序内部传输数据的接口和类。 java.awt.dnd Drag 和 Drop 是一种直接操作动作,在许多图形用户界面系统中都会遇到它,它提供了一种机制,能够在两个与 GUI 中...

    JAVA 清华大学 教程

    ★ 第六讲 Java的线程和Java Applet ◇课前索引 ◇6.1 线程简介 ◇6.2 多线程的互斥与同步 ◇6.3 Java Applet ◇本讲小结 ◇课后习题 ★ 第七讲 Swing用户界面设计 ◇课前索引 ◇7.1 Swing简介 ◇7.2 ...

    java 面试题 总结

    以下程序使用内部类实现线程,对j增减的时候没有考虑顺序问题。 public class ThreadTest1{ private int j; public static void main(String args[]){ ThreadTest1 tt=new ThreadTest1(); Inc inc=tt.new Inc(); ...

    [Java参考文档]

    java.awt.datatransfer 提供在应用程序之间和在应用程序内部传输数据的接口和类。 java.awt.dnd Drag 和 Drop 是一种直接操作动作,在许多图形用户界面系统中都会遇到它,它提供了一种机制,能够在两个与 GUI 中...

    清华大学JAVA教程

    ★ 第六讲 Java的线程和Java Applet ◇课前索引 ◇6.1 线程简介 ◇6.2 多线程的互斥与同步 ◇6.3 Java Applet ◇本讲小结 ◇课后习题 ★ 第七讲 Swing用户界面设计 ◇课前索引 ◇7.1 Swing简介 ◇7.2 ...

    Java编程语言详细教程

    ★ 第六讲 Java的线程和Java Applet ◇课前索引 ◇6.1 线程简介 ◇6.2 多线程的互斥与同步 ◇6.3 Java Applet ◇本讲小结 ◇课后习题 ★ 第七讲 Swing用户界面设计 ◇课前索引 ◇7.1 Swing简介 ◇7.2 ...

Global site tag (gtag.js) - Google Analytics