In this feature article, Ian Darwin (author of O'Reilly's Java Cookbook) provides examples of Java's beautiful Reflection API, which allows your code to reach down into the JVM and do some of the same things that the Java runtime does: discover and load class files, instantiate classes, discover and invoke constructors and methods, discover and set/get fields, and more.

Mirror, mirror, on the wall...

No, this is not about me looking at myself, or even my own code. Rather, it's my nomination for the Beautiful Code API. There is plenty of beautiful stuff in the Java SE API, but to my mind one of the most sublime pieces is Sun's Reflection API. While some dynamic languages let you do what Reflection does, I'm not aware of any other compiled, strongly-typed language (other than, perhaps, Java knock-offs like C#) that have anything like it.

So what is Reflection? Also known as Introspection, the Reflection API allows you to operate on classes and objects in ways such as the following:

  • Load a class file into memory at run time, knowing only its name;
  • Given a class, examine its methods, fields, constructors, annotations, and so on;
  • Given a class, invoke constructors and methods;
  • Given a class and an instance, access fields;
  • Given an interface, create proxies for it dynamically.

A class named Class

It might seem strange to have "a class named Class" (maybe no more so than creating an object of class Object, I guess). But java.lang.Class has been around since the earliest days of Java; at least JDK 1.0, so I guess most of these uses were planned even then.

Time for a code example. Suppose you've invented a new API called a Showlet, sort of a cross between an Applet and a Servlet. You think lots of people will want to write their own Showlets. Create an interface for it:


package showoff;

public interface Showlet {
	public void show();
}

Publicize it (this step omitted from this article; you're on your own). Now whenever somebody wants to write a showlet, they just implement your public interface. Say I write one called IanShow:


package com.darwinssys.jellybeans;
import showoff.Showlet;
public class IanShow implements Showlet {
	public void show() {
		System.out.println("OK, here's what I show: A234JQ");
	}
}

Nothing very elaborate, but enough to show (so to speak) the operation. Your code will need to load this class, even though my class was written after your class, so you can't have a compile-time dependency on my class. However, to use it is no problem:


public class MyBigApp {
	public static void main(String[] args) throws Exception {
		String className;
		// stub getting name of user-defined class from config file
		className = "com.darwinsys.jellybeans.IanShow";

		// Create this user's ShowLet
		Class c = Class.forName(className);
		Showlet s = (Showlet)c.newInstance();

		// Now we have a showlet, make it do its thing:
		s.show();
	}
}

The whole magic part is the two lines of code below the comment "Create this user's Showlet". The first line uses the Class class' static forName() method to dynamically load the IanShow.class file from your classpath into the JVM. At this time the class file will be found, inspected, verified, and loaded into memory; after this it is treated pretty much like any other class in your application. The second line creates an instance of this class. The main requirement for this to succeed is that there must be a public, no-argument constructor in your class. Since this is the default constructor in Java, it's a safe bet. But in case the user messes up, one of a variety of Exceptions is just waiting to be thrown. See the JavaDoc, or compile this code in an IDE with the throws clause commented out. In a real "extensible application" model, you'd want to catch some of these and give better warnings.

One of the most annoying problems is ClassCastException, which would happen if the user provided a class that doesn't implement the Showlet interface. This would occur after the newInstance() call but before the assignment to variable "s". To prevent this exception, you'd normally use the built-in instanceof operator, but that requires the class be known at compile time. There is an isInstance method in the Class class; a more cautious version of the Showlet creation is thus:


	Class c = Class.forName(className);
	Object o = c.newInstance();
        if (o instanceof Showlet) {
		Showlet s = (Showlet)c.newInstance();
		...
	} else {
		System.err.printf("Sorry, class %s is not a Showlet%n",
			className);
	}

What does all this give you? An extension or plug-in mechanism that is completely independent of user-defined classes. As long as they correctly implement your published interface, they will load and run.

Plan B

If for some reason you prefer inheritance, make Showlet be an abstract class with show() an abstract method. The instance classes then extend this rather than implement it. Everything else is pretty much the same.

Getting to Class

Class.forName() is one way of getting a Class descriptor, and it's familiar to anybody who's written a "JDBC 101" program (even though it's not how you get your database driver in real life). There are two other ways of getting a Class descriptor.

If the class whose descriptor you want is known at compile time, just say typeName.class. The "class" keyword in Java, if it appears after a "." with a type name before that, generates an expression of type "Class" for the given type. So String.class returns the same as Class.forName("java.lang.String"), for example.

Finally, if the class is not known but you have an object of the class, you can ask it for its class.


	Class c = someRandomObject.getClass();
	println("Object is of class " + c.getName());

What does this give you? One way or another, you should now be able to get a Class descriptor for any class in a Java program.

MyJavaP

The standard JDK has always included a program called javap, the Java printer. Javap has two main functions: it provides a quick view of a class' external structure, and it provides a detailed dump of a class' internal byte code. The latter is beyond the scope of the Reflection API; you would have to use a byte code library such as the Apache Byte Code Engineering Library (BCEL). The former, however, can easily be implemented using Reflection. When run against java.lang.Object, the Java SE implementation produces this output:


Compiled from "Object.java"
public class java.lang.Object{
    public java.lang.Object();
    public final native java.lang.Class getClass();
    public native int hashCode();
    public boolean equals(java.lang.Object);
    protected native java.lang.Object clone()       throws java.lang.CloneNotSupportedException;
    public java.lang.String toString();
    public final native void notify();
    public final native void notifyAll();
    public final native void wait(long)       throws java.lang.InterruptedException;
    public final void wait(long, int)       throws java.lang.InterruptedException;
    public final void wait()       throws java.lang.InterruptedException;
    protected void finalize()       throws java.lang.Throwable;
    static {};
}
I wrote a simple clone of javap, called MyJavaP. An earlier version of this was contributed to the Kaffe project. The output is as follows:

class java.lang.Object {
        public java.lang.Object()
        public native int java.lang.Object.hashCode()
        public final native java.lang.Class java.lang.Object.getClass()
        protected void java.lang.Object.finalize() throws java.lang.Throwable
        protected native java.lang.Object java.lang.Object.clone() throws java.lang.CloneNotSupportedException
        public final native void java.lang.Object.wait(long) throws java.lang.InterruptedException
        public final void java.lang.Object.wait() throws java.lang.InterruptedException
        public final void java.lang.Object.wait(long,int) throws java.lang.InterruptedException
        public boolean java.lang.Object.equals(java.lang.Object)
        public java.lang.String java.lang.Object.toString()
        public final native void java.lang.Object.notify()
        public final native void java.lang.Object.notifyAll()
}

As you can see, it misses some details, and the static code block. But, for a simple implementation (about sixty lines), it does not badly. The core of the implementation is shown in these twenty lines of code:

Class c = Class.forName(className);
System.out.println(c + " {");

int mods;
Field fields[] = c.getDeclaredFields();
for (Field f : fields) {
	if (!Modifier.isPrivate(f.getModifiers())
	 && !Modifier.isProtected(f.getModifiers()))
		System.out.println("\t" + f);
}
Constructor[] constructors = c.getConstructors();
for (Constructor con : constructors) {
	System.out.println("\t" + con);
}
Method methods[] = c.getDeclaredMethods();
for (Method m : methods) {
	if (!Modifier.isPrivate(m.getModifiers())) {
		System.out.println("\t" + m);
	}
}
System.out.println("}");

Membership Lists

Suppose you want to become a famous Java author by creating a big fat book full of API cross-reference. Knowing there are new releases of Java SE every 12-18 months, do you:

  • a) Read the javadoc, and type up a huge document with all the information for each class, or
  • b) Write a program that extracts all this information mechanically, and sends it direct to your typesetting program?
If you answered "a", give yourself zero points, and thanks for playing! The correct answer is of course "b". In fact, using classes from java.util.zip along with Reflection makes this whole thing pretty easy. Once you have a Class object, there are methods in it with names like getConstructors(), getFields(), getMethods(), and so on. Each returns an array of descriptor objects, e.g. Constructor, Field, Method. These classes in java.lang.reflect (and their parent class Member) provide detailed information about one member in the given class. For example, a Method object contains the corresponding method's name, visibility, argument list, and so on. If a method is overloaded, each overload will return one Method.

The basic idea for the cross reference program, then, expressed as pseudo-code, is:


for (ZipEntry entry : new ZipFile(name).entries()) {
    if (entry represents a Class) {
	Class c = Class.forName(entry.getName());
	for (Field f : c.getMethods()) {
		print a field;
	}
	for (Method m : c.getMethods() {
		print a method;
	}
    }
}

Of course, the real code is a bit more complex. And, in fact, I wrote it with the view that I might want to re-use parts of the code, so the outer loop and the "if entry represents a class" logic are in the abstract class APIFormatter; the logic of what to do with a given class is deferred to the template method doClass() in a subclass. The standard example is CrossRef, but there is another usage example in the JUnit test case APIFormatterTest. Finally, CrossRefXML extends CrossRef and overrides some of the output methods to output an XML document instead of a text document.

JavaBean Introspector

Several APIs use classes from the Reflection API. The JavaBeans API (java.beans) was both designed as a simplification layer to make it easier to use reflection for the less-ambitious task of getting an object's list of "properties" - fields that have setter/getter method pairs- and hence to make it easy for GUI builder tools to discover information about "Java Beans". The spec included the now-well-known setter/getter accessor pattern, requirement of a no-argument constructor, and the optional BeanInfo configuration file. Sun hoped and expected that tool building companies would produce GUI builders (based on JavaBeans) that would compete with Visual Basic. Arguably they have done so, in tools like Eclipse and NetBeans with their respective visual builders.

The Introspector is the main class you need to know. Its getBeanInfo() method takes a class name and returns a general-purpose BeanInfo object. This represents the list of properties either exposed by the bean or specified in the eponymous configuration file.

A new methodology - Dynamic Method Invocation

If you have a Method descriptor, you can invoke that method on any object of a class that contains it. Just call the Method's invoke() method passing the object (you can pass null if you're invoking a static method), and the argument list packed as an array of Object. Assume you are given class X containing this method:


public void work(int i, String s) {
	System.out.printf("Called: i=%d, s=%s%n", i, s);
}
To find and invoke this method dynamically, given an instance of it called "x", all you need to do is:

	Class clX = x.getClass();

	// To find a method, need array of matching Class types.
	Class[] argTypes = { int.class, String.class };

	// Find a Method object for the given method.
	Method worker = clX.getMethod("work", argTypes);

	// To invoke the method, need the invocation
	// arguments, as an Object array.
	Object[] theData = { 42, "Chocolate Chips" };

	// The last step: invoke the method.
	worker.invoke(x, theData);

By itself this is a bit tedious to code, but it is background for the next few sections.

Dynamic Proxy and AOP

The Proxy pattern is well known: one object stands in for another. A Proxy can be created in Java using an interface and two classes, the "real" implementation and a surrogate or wrapper which implements the same interface and ultimately forwards each method call through to the "real" implementation. For example, if I want to create a Proxy for the Showlet example above, say, to verify the user's credentials before passing control to the provided Showlet, a do-nothing proxy impementation can be as simple as this:


public class ShowletProxy implements Showlet {
	Showlet realObject;	// set in constructor
	
	public void show() {
        	realObject.show();
	}
}

In real life the Proxy can do all sorts of other things, such as testing security, logging method calls and their parameters, network calls (used in RMI and EJB), and so on.

A more complete hand-written Proxy might look like this:


public class ShowletProxy implements Showlet {
	Showlet realObject;	// set in constructor
	
	public void show() {
		final String className = realObject.getClass().getName();
		if (securityOK()) {
			log("About to call " + className);
			realObject.show();
			log("Completed " + className);
		} else {
			log("Security - rejected " + className);
		}
	}
}

The downside of this is that it is tied to a particular interface, namely Showlet. What if you want to proxy ten, a hundred, or a thousand classes? It just doesn't scale. You need a way to write the proxies dynamically. That is, of course, the dynamic proxy mechanism. Introduced to Java in Java SE 1.3, the dynamic proxy mechanism in class java.lang.reflect.Proxy allows you to create a proxy to any interface dynamically, given only the interface and a general-purpose InvocationHandler. The InvocationHandler is where you specify what to do before and after the method invocation. An InvocationHandler allows you full control over the actual invocation of methods in the "real" object that is being proxied. There is only one method in the Invocation handler interface; a typical implementation might look something like this:


class MyInvocationHandler implements InvocationHandler {

	private Object realObject;	// set in Constructor

	/**
	 * Method that is called for every call into the proxy;
	 * this has to invoke the method on the real object.
	 */
	public Object invoke(Object proxyObject, Method method, Object[] argList)
		throws Throwable {
		log("About to call " + className + "." + method.getName());
		Object ret = method.invoke(realObject, argList);
		System.out.println(" Completed.");
		return ret;
	}
}

The InvocationHandler's invoke() method is where the dynamic proxy calls your code; the "method.invoke()" is where your proxy calls the real object's method. The names are the same, but they are different steps along the chain, and the argument lists differ. Although the InvocationHandler's invoke() method is passed a reference to the dynamic proxy, it is not passed an reference to the "real" object, so this has to be provided in the class, either by a Constructor or (for greater flexibility) in a set method.

To create the dynamic proxy, use the Proxy class' newProxyInstance() method, which requires a ClassLoader (see below), one or more interfaces that are to be handled (as an array of Class objects), and a reference to the InvocationHandler:


Showlet generatedProxy = (Showlet) Proxy.newProxyInstance(
	Showlet.class.getClassLoader(),
	new Class[] { Showlet.class }, handler);

Because it's a nuisance to create the InvocationHandler and the Dynamic Proxy, this is normally delegated to a Factory method. Factory is another well-known design pattern used throughout Java: a class makes up objects for you (see for example Locale.getInstance() and Calendar.getInstance()).

In the code download you will find a class called DynamicProxyFactoryDemo which implements a Factory for the proxies; note that the main program now has no idea that proxying is going on; it deals only in the interface (and the factory).


	public static void main(String[] args) {

		Showlet showlet = ShowletFactory.getInstance();
		System.out.println("Showlet Proxy object is " + 
                      showlet.getClass().getName());
		System.out.println("All done");
	}
What does this give you? With Dynamic Proxy, you can create one proxy that will proxy all (or selected) requests for a huge number of methods on a large number of objects. However, the proxying has some setup complexity, so it's best if you can abstract object creation into the factory.

Aspects of change

A more generic way of handling this notion of proxying is to use programming language constructs to help automate it. This has lead to the rise of "Aspect Oriented Programming", or AOP. AOP uses some interesting vocabulary, but an "Aspect" is some function (such as logging or validation) that needs to applied automatically to a range of classes. Two important AOP implementations are Aspect/J (original site at PARC; current site at Eclipse.org) and the Spring Framework AOP. Spring provides a very general-purpose Bean Factory that is configured entirely by a configuration file, and a large array of pre-written beans. Useful in this context is their AutoProxyFactoryBean, which will automatically apply proxying to an arbitrary number of methods based on several seclection mechanisms, including one that uses Regular Expressions.

Since I'm sure there will be a BC article on Spring, I won't steal this article's thunder, but if you want a peek meantime, check out the Spring Framework site.

ClassLoaders and SecurityManagers and more, oh my

One topic I've not covered here is the notion of security. Java provides a SecurityManager class that can be used to limit what classes can do. A ClassLoader is, of course, the object that is responsible for loading classes. Java provides a default ClassLoader, but you can write your own. The topics of ClassLoaders and SecurityManagers are important, but this article is already at its maximum length. I urge you to learn about these topics, especially if you are going to be using dynamic classloading of classes provided by other, possibly untrusted, entities. These topics are discussed in my Java Cookbook (O'Reilly, 2e 2004) as well as in the Sun-provided documentation.

Conclusion

The Reflection API is truly sublime, because it allows your code to reach down into the JVM and do some of the same things that the Java runtime does: discover and load class files, instantiate classes, discover and invoke constructors and methods, discover and set/get fields, and more. In this Beautiful Code, I've shown some real-world code that uses this beautiful API.

Footnote: Downloads

The examples in this article are mostly drawn from the code that accompanies my Java Cookbook (my page; O'Reilly page), although the code has been updated since the Second Edition went to print. You can download the entire zip file if you wish. There is also a much smaller zip file of just the examples from the Reflection package (subdirectory) of the Java Cookbook. Note that some of the later examples use an interface called Quote instead of Showlet, but the functionality of the proxying is the same. The Quote service gives out pithy sayings, not stock price quotations.

Ian Darwin is the author of O'Reilly's Java Cookbook, but also wrote the Nutshell book Checking C Programs with Lint and more recently Checking Java Programs with Open Source Tools; he is also co-author of the 1985 cult classic "Can't Happen, or /* NOTREACHED */, or Real Programs Dump Core" which in its way and in its day taught developers to change ugly code into beautiful code.