Older blog entries for michi (starting at number 2)

Why I don't like Java RMI and how I use it anyways

The Java Remote Method Invocation API is a great thing to have because it is available in almost every J2SE runtime environment without adding further dependencies. However there are some implications when using RMI and I just cannot get my head around them:

  1. Interfaces used as remote interfaces need to extend java.rmi.Remote. Interfaces should be clean and not contain any clutter introduced by a certain technology. This is even more true with modern frameworks and things like dependency injection.
  2. Remote methods need to declare java.rmi.RemoteException in their throws clause. This is basically a continuation of the first point. This point holds, even if you ignore the rant about checked exceptions, which I don’t want to comment on right now.
  3. Remote objects need to be exported explicitly. Even though one explicitly declared which methods should be accessible from a remote site with the above two points, one still needs to explicitly export every single instance of an object implementing those methods.

Don’t get me wrong, all those implications have their right to exist because the decisions leading up to them were made for a reason. But in some circumstances those reasons don’t apply. It is just not the one-to-rule-them-all solution for remote method invocation in Java.

There are ways around those problems. One could for instance duplicate the existing interfaces to fit the needs of RMI. But frankly speaking, I just don’t want to do that myself.


That being said, lets see if the task of separating the transportation layer based on RMI from your precious interfaces can be automated in some way, so it doesn’t have to be done by hand. The following are the key points of the approach:

  • Interfaces can explicitly be marked as remote interfaces at runtime without the need for recompiling them. All methods exposed by such an interface can be invoked from a remote site. All parameters which are subclasses of such interfaces, will be passed by-reference and will not be serialized. This is just the same behavior as if the interface would extend java.rmi.Remote in the RMI world. The actual remote interfaces are generated on-demand at runtime.
  • Provide a proxy factory which supports the rapid development of a transportation layer based on RMI for given clean interfaces. The interface classes do not need to be cluttered with specifics of the transportation implementation.
  • A proxy in this context is a transparent object implementing both, the local and the generated remote interface. Both interfaces are usable:
    • Cast the proxy to java.rmi.Remote and use it with any naming or registry service available to the RMI world. Every proxy implicitly is a remote object without the need for explicitly exporting it.
    • Cast the proxy to your local interface and don’t bother whether it actually targets a local or a remote site.
  • The decision how an invocation actually is dispatched can be solely based on whether the target object of a proxy is a remote or a local one. This decision is hidden inside the transportation layer.

Available as a download attached to this post you’ll find a first reference implementation of such a proxy factory as described above. Note that it is just a sketch to illustrate my point and will probably contain major flaws. Also it brings a dependency on Javassist, which kind of contradicts the very first sentence of this post. However it is capable of distributing this tiny example across several sites without modifying the given interfaces, which also represents my only test-case:

public interface Client {
	public void callback(String message);
}

public interface Server {
	public void subscribe(Client subscriber);
	public void notify(String message);
}

public class ClientImpl implements Client {
	public void callback(String message) {
		// ... do some important job ...
	}
}

public class ServerImpl implements Server {
	public void subscribe(Client subscriber) {
		// ... remember "subscriber" in some fancy data structure ...
	}
	public void notify(String message) {
		// ... invoke all "subscribers" like they were local ...
	}
}

This is my attempt to show how I personally think that RMI should have been designed in the first place. Please feel free to comment, improve, ignore or flame.

Syndicated 2010-04-06 20:05:16 from michi's blog

Cacao supports JMX Remote Monitoring and Management

Since a few days Cacao successfully starts OpenJDKs JMX Monitoring and Management Agent if requested to do so. This allows you to remotely connect to Cacao with any JMX-compliant monitoring tool. One of the main responsibilities of this agent is to act as a server for MBeans (managed beans). The JRE provides some basic MBeans which allow out-of-the-box monitoring and management of VM internals. But applications can easily extend the functionality by providing custom MBeans. If you want to learn more about this topic, you should visit OpenJDKs JMX group.

One such JMX-compliant monitoring tool is JConsole which comes bundled with most J2SDK installations. Below you see a JConsole from Apples Java running on my MacOS X workstation connected to Cacao running on a remote Linux machine.

JConsole connected to Cacao

Note that there (still) are some restrictions on the current support:

  1. Some of the VM internal management functions are not yet fully implemented. Those functions are defined by HotSpots JMM interface (the thing called jmm.h). It will take some time and patience until all of them are implemented.
  2. Only OpenJDK provides a reference implementation of the JMX agent, so at the moment there is no support for GNU Classpath.
  3. The thing that baffled me most, was that the documentation stated that applications running on the same machine inside another HotSpot VM process can be monitored without starting the JMX agent. I found out that HotSpot creates a shared memory region to which you can attach another VM process. I don't like the idea of sharing memory across VM processes at all, so Cacao does not (and probably never will) support this feature. But I implemented the necessary stubs to avoid UnsatisfiedLinkageErrors and make everything run smoothly. So don't wonder if you can't see a list of locally running Cacao processes in JConsole. If you are interested, all the functionality to access this shared memory is hidden in sun.misc.Perf.

And finally, how do you make Cacao start the JMX agent? Try the snippet below. If you want to know more about those magic properties, try one of the thousand other articles out there dealing with this topic.

$ java -Dcom.sun.management.jmxremote \
        -Dcom.sun.management.jmxremote.port=9999 \
        -Dcom.sun.management.jmxremote.authenticate=false \
        -Dcom.sun.management.jmxremote.ssl=false

Have fun monitoring and managing!

Syndicated 2009-10-28 19:13:32 from michi's blog

First blog post

After several months of struggle and countless efforts trying to avoid it, I finally did it. This is my very first blog post. Furthermore it is a greeting to all the people out there who are interested in what I have to say.

Syndicated 2009-10-26 17:29:32 from michi's blog

New Advogato Features

New HTML Parser: The long-awaited libxml2 based HTML parser code is live. It needs further work but already handles most markup better than the original parser.

Keep up with the latest Advogato features by reading the Advogato status blog.

If you're a C programmer with some spare time, take a look at the mod_virgule project page and help us with one of the tasks on the ToDo list!