现在的位置: 首页 > 综合 > 正文

RMI Spy对程序运行产生的影响(Eclipse 的RMI插件)

2012年09月22日 ⁄ 综合 ⁄ 共 3436字 ⁄ 字号 评论关闭

本文档描述了使用RMI Spy会对你的应用程序的执行产生怎样的影响。

在大多数情况下,你不会注意到我们程序执行时的任何不同。但是,如果你的程序没有按照你预期去执行,此时,你将会意识到RMI Spy能为你调试程序带来的方便了。这是一个技术文档,而不是一个RMI Spy帮助文档。

1,RMI Spy是什么?
RMI Spy负责收集和显示你的应用程序运行时产生的和RMI相关的事件。具体的说,它监控所有的远程调用(包括你应用程序产生的外部调用和其他应用程序调用你的应用程序提供的远程服务)。它同时可以显示类加载事件,从而帮助你调试"类加载"问题,这些问题通常会出现在RMI系统开发的过程中。

2,RMI Spy是如何工作的?
i)介绍:
RMI Spy的工作基于Logging API,这些Logging API被RMI接口使用。如果RMI Spy没有被开启,你可以手动开启"logging properties"(你可以在RMI运行配置的"RMI Launch"标签里勾选开启)以及用来监控输出的控制台窗口。

比如:打开"java.rmi.server.logCalls"属性,产生类似下面的输出(为显示清楚,添加了换行符):

20/05/2006 13:35:06 sun.rmi.server.UnicastServerRef logCall
FINER: RMI TCP Connection(2)-192.168.2.100: [192.168.2.100: \
       demo.rmi.print.server.RemotePrinterImpl[1]: \
       public abstract int demo.rmi.print.server.RemotePrinter.submitJob( \
           java.lang.String) throws java.rmi.RemoteException]

这样的输出并不利于阅读,也没有提供任何有意义的信息。


ii)RMI Spy接口

RMI Spy并不分析程序的输出(尽管理论上它能够分析),因为这个方法并不可靠---程序的输出可能会干扰RMI日志。取而代之的是,它与RMI的日志系统衔接,并能在事件产生时及时捕获。RMI Spy运行组件(作为应用程序的一部分运行)使用日志API(Logging API)来注册它自己的代理从而收集RMI事件并将它们推送给RMI插件进行分析并显示在RMI Spy视图中。

为了避免修改应用程序代码,RMI Spy使用了一个启动封装器(launch wrapper)。这意味着RMI Spy的运行组件是运行在你的程序内部的(当然,前提是RMI Spy被激活了)。当应用程序启动后,RMI Spy JAR会被添加到classpath,launch wrapper(类net.genady.rmi.logger.Runner)将被作为主类(main class)。应用程序的主类和参数会被当做参数传递到launch wrapper。

launch wrapper 负责主持日志代理(logging handlers),同RMI 插件建立一个TCP连接,并且经控制权传递给真正的应用程序。显而易见的是,在同一个VM进程中同时运行wrapper,这对于你的应用程序是有影响的。
下一节就会讨论这些影响的细节。

iii)仪器的使用(The use of instrumentation)
RMI插件使用字节码仪器(ASM库)来执行一些高级功能(比如时间测量)。它将不会对你的程序产生任何特别的影响,因为它只执行非常非常少的一些系统类。需要说明的是,RMI插件必须使用JDK1.5或者JDK1.6版本(如果使用的版本不对,插件将自动关闭),这意味着如果你使用自己的仪器工具(-javaagent)的话,你就要多加小心了,当然,在大多数情况下,这个不是问题。

RMI Spy会调用某些对象的一些方法,这些对象会在远程调用过程中作为值传递的参数或者返回值。在以下类中,它会选择调用toString()方法:所有的原始类型,封装类,RULs和URIs,InetAddress,枚举类型,字符序列( CharSequence)的实现和数字类(Number class)的子类。它同样会在集(Collection)的实现中调用size()方法。这些方法的调用会产生无法预期的副作用,比如获取锁/监视器,创建网络连接等等。

3,运行模式和调试模式的不同
RMI Spy没有使用调试API,因此,在运行模式和调试模式下,RMI Spy的操作没有任何区别。

4,支持的JDK/JVM提供商
RMI Spy依赖于Sun的内部API。但是,很多运行RMI的JDK提供者都是由Sun授权许可的,因此,大多数标准JVM都可以运行RMI Spy。要获取最新的兼容性列表,请访问website

5,堆栈跟踪
RMI Spy使用一个简单的启动封装器来运行一些配置,然后通过reflection APIs将控制权交个你的主类(main class)。因此,所有由主线程中产生的堆栈追踪会有以下的几行提示(假设你的主类是:demo.rmi.print.client.PrintClient):

at demo.rmi.print.client.PrintClient.main(PrintClient.java:35)
   at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
   at sun.reflect.NativeMethodAccessorImpl.invoke(
                             NativeMethodAccessorImpl.java:39)
   at sun.reflect.DelegatingMethodAccessorImpl.invoke(
                             DelegatingMethodAccessorImpl.java:25)
   at java.lang.reflect.Method.invoke(Method.java:324)
   at net.genady.rmi.logger.Runner.main(Runner.java:138)

堆栈追踪在其他的线程里产生,并且不会产生影响。

6,辅助线程
应用程序和RMI插件的通信时通过本地TCP连接进行的。尽管是本地连接,它仍旧有可能因为各种原因而被阻塞(比如本地防火墙)。因此,当有事件要传送给RMI插件是,运行组件会把那个事件放到事件队列中,专用守护线程会执行所有的通信工作。通过这种方法,应用程序线程永远不会被RMI插件阻塞,而对应用程序的影响将会降到最低。这个专用守护线程的名字是"RMI Plug-in for Eclipse Log Events Reporter",大多数时候,它是空闲的。

7,关闭钩子(A Shutdown hook)
一个应用程序调用方法System.exit()或者相似方法来结束执行的情况是常见的。在这种情况下,RMI Spy的运行组件必须确保所有被收集的事件都已经被传送给运行在eclipse中的RMI Spy部分了。为了达到这个目的,RMI插件使用了"shutdown hooks"功能。因此,这可能会花费较长的事件去关闭一个应用程序(直到所有的应用程序都被传送)。通常,这个过程花费几毫秒,但对于RMI密集型程序,这个过程会多用10到100毫秒直到程序终止。

8,使用RMI的Logging属性(Logging properties)
RMI Spy没有直接使用任何logging属性,因此,你可以开启他们来查看正常的基于控制台的日志。但是,设置某些属性,比如"sun.rmi.server.suppressStackTraces"会导致RMI Spy丢失某些信息。因此最好让RMI Spy来显示这些日志信息兵,要避免直接修改这些日志属性。

9,使用日志API

(这需要更多的技术和对Logging APIs的了解)RMI Spy把RMI loggers的logging level修改为"ALL"。你之所在控制台上看不到RMI的日志是因为RMI日志的控制者拥有更高的等级(默认是"SILENT")。如果因为某些原因日志控制者等级被修改了,或者另一个控制者被注册到RMI日志,他们将获取他们本不会获取到的事件(如果RMI
Spy没有被使用的话)。当然,如果你手动修改了RMI日志等级,你就可以影响RMI Spy的行为了。

英语原文:http://www.genady.net/rmi/v20/docs/spy/spy_effects.html

抱歉!评论已关闭.