RMI Plug-in for Eclipse
This document describes how using the RMI Spy will affect the
execution of your applications.
Table of contents
The RMI Spy collects and displays the RMI-related runtime events generated by your application. Specifically it monitors all the remote calls (both outgoing calls made by your application and incoming calls, made by another application and serviced by your application). It also displays the class loading events, to help you debug classloader problems that are common during the development of RMI systems.
The RMI Spy is based on the Logging API that is used by the RMI implementation. Even if you don't use the RMI Spy, it is possible to manually turn on the logging properties (you can do that in the "RMI VM Properties" launcher tab) and monitor the output in the console window. For example, turning on the "java.rmi.server.logCalls" property, produces output similar to the following (line breaks added for clarity):
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: \ public abstract int demo.rmi.print.server.RemotePrinter.submitJob( \ java.lang.String) throws java.rmi.RemoteException]
Such output is not human-friendly and extracting any useful information requires much effort.
The RMI Spy Implementation
The RMI Spy does not parse the program's output (although in theory it could do that) because this method is not reliable - the program's output could interfere with the RMI log. Instead, it hooks into the RMI logging system and catches the events at the moment they are generated. The RMI Spy runtime component (that runs as part of the application) uses the Logging API to register its own handlers that collect RMI events and pass them to the RMI Plug-in where they are analyzed and displayed in the RMI Spy view.
To avoid modifying the application code, a launch wrapper is used.
That means that the runtime components of the RMI Spy are running inside
your application (of course, only when the RMI Spy is enabled). When you
launch the application the RMI Spy JAR is added to the classpath and the
launch wrapper (class
The launch wrapper is responsible for registering the logging handlers, establishing a TCP connection with the RMI Plugin and passing the control to the real application. Obviously running the wrapper with your application in the same VM can affect application's behavior. The next sections describes these effects in further detail.
The use of instrumentation
The RMI Plug-in for Eclipse uses bytecode instrumentation ( the ASM library ) to implement some of the advanced features (such as call duration measurement). It should not have any particular effect on your application (except what is presented below), as the RMI Spy instruments only few system classes, but using instrumentation requires using JDK 1.5 or JDK 1.6 to operate (it will be automatically disabled if you use a different version) and it means you should take extra care if you use your own instrumentation (-javaagent) tools (but that's not a problem in most cases).
RMI Spy calls some methods on the objects that are passed as values (or return values) of remote calls. In particular it calls the
The RMI Spy does not use the debugging APIs and therefore there is no difference in the operation of the RMI Spy between the Run and Debug modes.
The RMI Spy relies on Sun's internal APIs. However, the RMI implementation of many JDK vendor was licensed from Sun so the RMI Spy can work with most stand-alone JVMs. For the up to date compatibility list, please visit our website.
The RMI Spy uses a simple launch wrapper that performs some
configuration and then passes control to your main class through the reflection APIs. Therefore all stack traces
generated in the main thread will have the following lines at their
bottom (suppose your main class is
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)
Stack traces generated in other threads are not affected.
The communication between the application and the RMI Plugin for Eclipse is performed through a local TCP connection. Even though a connection is local it can block for various reasons (for example a local firewall). Therefore when there is an event to be passed to the RMI Plugin, the runtime component places that event in the events queue and a dedicated daemon thread performs all the communications work. This way, the application threads are never blocked by the RMI plugin and the impact on the application is minimal. The name of the daemon thread is "RMI Plug-in for Eclipse Log Events Reporter" and it is idle for most of the time.
It is not uncommon for an application to stop execution by calling System.exit() or similar method. In such case the RMI Spy's runtime component must ensure that all the events that were collected have been transferred to the RMI Spy part that is running inside Eclipse. In order to achieve this goal the RMI Plugin makes use of the shutdown hooks feature. Therefore it might take just a little longer for the application to terminate (until all the events are transferred). Usually it's only few milliseconds longer, but for RMI-intensive applications it can be another 10 or 100 milliseconds until the application terminates.
The RMI Spy does not use any logging properties directly, so you can turn them on to see the regular console-based logs. However, setting some properties, such as "sun.rmi.server.suppressStackTraces" can cause the RMI Spy to lose some information. Therefore it is best to let the RMI Spy to display the log information and avoid modifying the logging properties directly.
(This is a bit more technical and requires understanding of the Logging APIs) The RMI Spy changes the logging level of the RMI loggers to "ALL". The reason why you don't see the RMI logs on the console is that the RMI logging handlers have a higher logging level (the default is "SILENT"). If for some reason the logging level of the handlers is changed, or another handler is registered to the RMI loggers, they will receive events that they wouldn't receive if the RMI Spy wasn't used. Of course if you modify the logging level of the RMI loggers manually, you can affect the behavior of the RMI Spy.