JDK Dynamic Proxy


Introduction

Dynamic Proxy mechanism is part of the standard Java SKD implementation under the java.lang.reflect package. This mechanism allows to create ‘on the fly’ proxy implementation based one or more interface types which can then be used interchangeable at runtime. This process allows leveraging many known patterns in code dynamically like interceptor, decorator, adapter etc. In every case the primary motive is to ‘intercept’ the method calls and reroute or preprocess them to add or remove functional behaviors dynamically at runtime. Dynamic proxy classes are useful to an application or library that needs to provide type-safe reflective dispatch of invocations on objects that present public interfaces. To understand how proxying works it’s important to understand what the proxy pattern dictates.

The Proxy pattern – A Brief Review

The Proxy Pattern is an original Gang of Four (GOF) Structural pattern that was proposed way back in 1994 and was inducted in the Portland Pattern Repository subsequently. Theoretically the Proxy pattern involves decomposing the original implementation target into two separate and distinct objects namely the ‘stub’ (or ‘surrogate’) and the ‘skeleton’. Traditionally the stub objects resides on the client side and provides what is called ‘location transparency’ to the clients while as the skeleton resides on the server side and provides ‘location transparency’ to the intended implementation targets. The idea of ‘location transparency’ implies the both the clients and the target implementation are relieved of the responsibility of knowing where the other one resides. The process of creating these stub and skeleton objects based on an implementation target is called the proxying.

One very common example of remote proxying in standard Java is RMI. The Proxy pattern is used by Remote Method Invocation (RMI) to make an object executing in another JVM appear like a local object to its clients. This is the idea on which Enterprise JavaBeans (EJB) and CORBA work. Another example is JAX-RPC service invocation. While the clients deal with only the returning data values and the target service deals only with the processing and creation of the data values, it’s the proxy stubs and skeleton objects that do the dirty job of marshaling and unmarshalling the data, location identification of the target, service invocation, transaction demarcation etc.

But all this is about remote proxying where it is deemed that the client and targets don’t necessarily reside in the same JVM realm together. Sometimes the target to be proxied relies in the same JVM in which the client does. In such scenarios the actual full blown proxy mechanism is shrinked considerably to a very narrow boundary. Essentially the need to a skeleton object is reduced and in most cases deemed redundant at best and this also reduced the need for a stub or a surrogate. The proxy pattern gets reduced in most such cases to nothing more than a simple decorator pattern whose need may only be to induce an interceptor for pre or post processing of invocation calls made on the target or to audit stuff amongst other things. In such cases it is just enough to introduce a single intermediate temporary implementation between the client and target which conforms to the target’s public interface and which the clients can thus use interchangeably in place of the actual target implementation.

Today there are abundant provisions to generate such intermediate implementation both at compile time and runtime. Based on the use and complexity involved some implementations tend to depend only on runtime generation of stubs and skeletons like EJBs at deployment time. Dynamic proxy mechanism allows for the creation of a proxy object at run time without generating stub classes at compile time. In JDK 5.0 and later, the standard RMI facility now uses dynamic proxies instead of relying on generated stubs as it did earlier. Spring AOP is another beautiful example which relies heavily on dynamic proxies to accomplish many feats in Aspect orientation dynamically at runtime.

The Dynamic Proxy API

The JDK dynamic Proxy relies heavily on interface based implementations. The idea is pretty simple and extends from the core Object orientation philosophy of ‘coding to an interface’ instead of an implementation. The basic presumption here is to believe that we may need proxying on heavy objects which do a lot of service processing for business logic or service discovery in a good well build enterprise application. Thus use of interfaces in inevitable and also recommended for code scalability and maintainability. Based on this presumption the overall proxy API broadly breaks down to:

  • A target implementation: the class we intend to proxy.
  • A dynamic proxy class (simply referred to as a proxy class): a class that implements a list of interfaces specified at runtime. For smooth practical implementation, it is imperative that this proxy class implements at least one interface which the target implements. Though contractual obligations don’t dictate that this class should implement all the interfaces or should not implement new ones but down the processing line the proxy has to delegate the actual processing to the target sometime and one to one mapping between interface methods and implemented ones simplifies the overall design.
  • Proxy interfaces: is list of public interfaces that the proxy implementation should conform to. This list of interfaces is provided at runtime or declaratively.
  • Proxy Instance: the runtime instance of the dynamically generated proxy class.

Creating a JDK Proxy Class – A Primer

Each JDK proxy class has one public constructor that takes one argument, an implementation of the interface InvocationHandler. Each proxy instance has an associated invocation handler object, the one that was passed to its constructor. Rather than having to use the reflection API to access the public constructor, a proxy instance can be also be created by calling the Proxy.newProxyInstance method, which combines the actions of calling Proxy.getProxyClass with invoking the constructor with an invocation handler.

First we write our business interface which would be publically accessible to all clients.

public interface IAbc {
	Object greet(String msg) throws FooException;
}

Now a concrete service implementation which implements the IAbc interface.

public class AbcImpl implements IAbc {
       Object greet(Object obj) throws FooException {
               // actual business processing logic here...
       }
}

Now we write a dynamic proxy class MyLoggerProxy which intercepts the actual calls to methods on IAbc implementations and print a start and end log messages.

public class MyLoggerProxy implements java.lang.reflect.InvocationHandler {
	private Object obj;
       public static Object newInstance(Object obj) {
               return java.lang.reflect.Proxy.newProxyInstance(
                      obj.getClass().getClassLoader(),
                      obj.getClass().getInterfaces(),
                      new MyLoggerProxy(obj));
       }
       private MyLoggerProxy(Object obj) {
               this.obj = obj;
       }
       public Object invoke(Object proxy, Method m, Object[] args)
               throws Throwable{
        Object result;
        try {
            System.out.println("before method " + m.getName());
            result = m.invoke(obj, args);
        } catch (InvocationTargetException e) {
            throw e.getTargetException();
        } catch (Exception e) {
            throw new RuntimeException("unexpected invocation exception: " +
                                      e.getMessage());
        } finally {
            System.out.println("after method " + m.getName());
        }
        return result;
    }
}

To construct a MyLoggerProxy for an implementation of the IAbc interface and call one of its methods we need to use the dynamic proxy instead of the concrete class while keeping the reference bound to the interface IAbc.

IAbc abcObject = (IAbc) MyLoggerProxy.newInstance(new AbcImpl());
abcObject.greet("Test User");

Note that instead of using new AbcImpl we have injected a Dynamic Proxy on the right side. Since the left side of the invocation is types to the interface instead of Implementation so we can dynamically replace the right side as and when we may need. Only thing to keep track of is to ensure that the actual target we intent to proxy implements the interface that we are trying to assign the proxy instance to.

Dynamic Proxy Considerations and Limitations

Dynamic proxies can reduce a truck load of code that needs to be written to achieve the same level of functional flexibility as can be achieved with them. With a few hundred classes in our application trying to implement our simple example of MyLoggerProxy would prove to be a nightmare. As the classes in the overall application grow sequentially, effort required to add such functionality grows exponentially. To understand how and when can a dynamic proxy help us we need to delve into JDK proxy contracts.

Understanding Proxy Instance Properties

By contract, a proxy has a given set of properties. Some of the important ones which programmers need to remember and design around are as follows:

  • Proxy classes are always public and final and thus never abstract.

  • The actual runtime name of a proxy class is unspecified. The VM space of class names that begin with the string "$Proxy" is, however, reserved for proxy classes only.

  • A proxy class must extend java.lang.reflect.Proxy

  • A proxy class implements exactly the same number of interfaces specified at its creation and in the same given order.

  • If a proxy class implements a non-public interface, then it will be defined in the same package scope as that interface. Otherwise, the package of a proxy class is also unspecified and results in the default package qualifier being used.

  • Given a proxy instance abc and an interface IFoo which the proxy implements, the following would always return true:

                   abc instanceof IFoo

      and the following cast operation will succeed instead of throwing a ClassCastException

      (IFoo)abc

  • The static Proxy.getInvocationHandler method will return the invocation handler associated with the proxy instance passed as its argument. If the object passed to Proxy.getInvocationHandler is not a proxy instance, then an IllegalArgumentException  will be thrown

  • An invocation of the hashCode, equals, or toString methods declared in java.lang.Object on a proxy instance will be encoded and dispatched to the invocation handler’s invoke method in the same manner as interface method invocations are encoded and dispatched.

Methods Signatures Duplicated in Multiple Proxy Interfaces

As and when the application becomes bigger and complex, its very much possible to end up with more than one interfaces having the same method signatures. When two or more interface types of a proxy class contain a method with the same method signature, the order of the proxy class’s interfaces becomes significant. When such a duplicate method is invoked on a proxy instance, the java.lang.Method object passed to the invocation handler may not necessarily be the one whose declaring class is assignable from the reference type of the interface that the proxy’s method was invoked through. This limitation exists because the corresponding method implementation in the generated proxy class cannot determine which interface it was invoked through. Since this implementations is not accessible at compile time so a deferred runtime consideration is required. But then at runtime it is not possible to locate the target interface type correctly to which this proxy method belongs. Therefore, when a duplicate method is invoked on a proxy instance, the Method object for the method in the foremost interface that contains the method (either directly or inherited through a super interface) in the proxy class’s list of interfaces is passed to the invocation handler’s invoke method, regardless of the reference type through which the method invocation occurred. This limitation at times becomes a direct cause for Runtime exceptions and wrong logic processing issues. However there are ways using annotation meta data to help the proxy implementation locate the actual exact interface type to which the method being called belongs to.

Another special consideration is required for java.lang.Object class’s methods. It is possible for a proxy implementation to contains a method with the same name and parameter signature as the hashCode, equals, or toString methods of java.lang.Object. When such a method is invoked on a proxy instance, the Method object passed to the invocation handler will have java.lang.Object as its declaring class. This means that, the public, non-final methods of java.lang.Object logically precede all of the proxy interfaces for the determination of which Method object to pass to the invocation handler.

Proxies also handled unknown checked exceptions rather differently in the duplicate method scenario. When a duplicate method is dispatched to an invocation handler, the invoke method should only throw checked exception types that are assignable to one of the exception types in the throws clause of the method in all of the available proxy interfaces that it can be invoked through. If the invoke method throws a checked exception that is not assignable to any of the exception types declared by the method in all of the the proxy interfaces that it can be invoked through, then an unchecked UndeclaredThrowableException will be thrown by the invocation on the proxy instance. This restriction means that not all of the exception types returned by invoking getExceptionTypes on the java.lang.Method object passed to the invoke method can readily be thrown successfully by the invoke method.

Serialization of Proxies

Since java.lang.reflect.Proxy implements java.io.Serializable, proxy instances can be serialized as just about any seralizable type in Java. If a proxy instance contains an invocation handler that is not assignable to java.io.Serializable, however, then a java.io.NotSerializableException will be thrown if such an instance is written to a java.io.ObjectOutputStream. Similarly for proxy classes, implementing java.io.Externalizable, it has the same effect with respect to serialization as implementing java.io.Serializable viz: the writeExternal and readExternal methods of the Externalizable interface will never be invoked on a proxy instance (or an invocation handler) as part of its serialization process. As with all Class objects, the Class object for a proxy class is always serializable.

By design a proxy class never has any serializable fields and always has a serialVersionUID of 0L. This means that when the java.lang.Class object for a proxy class is passed to the static lookup method of java.io.ObjectStreamClass, the returned ObjectStreamClass instance will have the following behaviors:

  • Invoking its getSerialVersionUID method will always return 0L.
  • Invoking its getFields method will return an array of length zero.
  • Invoking its getField method with any String argument will return null.

    To understand how the Serialization process identifies and constructs the proxy object back and forth we need to stem back to the type code offsets in the Object serialization stream protocol. The  protocol for Object Serialization supports a type code named TC_PROXYCLASSDESC, which is a terminating symbol in the AST grammar for the stream format; its type and value are defined by the following constant field in the java.io.ObjectStreamConstants interface:

       final static byte TC_PROXYCLASSDESC = (byte)0x7D;

The AST grammar also includes the following two rules for processing and deciding on the stream termination logic:

newClassDesc:

        TC_PROXYCLASSDESC newHandle proxyClassDescInfo

proxyClassDescInfo:

    (int)<count> proxyInterfaceName[count] classAnnotation superClassDesc

When an ObjectOutputStream serializes the class descriptor for a class that is a proxy class, as determined by passing its Class object to the Proxy.isProxyClass method, it uses the TC_PROXYCLASSDESC type code instead of TC_CLASSDESC as is normally used for regular java classes. Now following the rules above, in the expansion of proxyClassDescInfo, the sequence of proxyInterfaceName items are the names of all of the interfaces implemented by the proxy class, in the order that they are returned by invoking the getInterfaces method on the Class object. The classAnnotation items are treated normally and hold the same meaning as they do for regular Classes. However for a proxy class, superClassDesc is the class descriptor for its own immediate superclass which is the java.lang.reflect.Proxy. When an ObjectInputStream encounters the type code TC_PROXYCLASSDESC, it deserializes the class descriptor for a proxy class from the stream as described above. Instead of calling its resolveClass method to resolve the java.lang.Class object for the class descriptor of the proxy, the following method in java.io.ObjectInputStream is called instead:

protected Class resolveProxyClass(String[] interfaces)

                 throws IOException, ClassNotFoundException;


The list of interface names that were deserialized in the proxy class descriptor are passed as the interfaces argument to resolveProxyClass. The default implementation of resolveProxyClass in ObjectInputStream returns the results of calling Proxy.getProxyClass with the list of Class objects for the interfaces named in the interfaces parameter.

The Class object used for each interface name i is the value returned by calling

Class.forName(i, false, loader)

    where:

          – loader is the first non-null class loader up the execution stack, or null if no non-null class loaders are on the stack.

If for any reason the Proxy.getProxyClass throws an IllegalArgumentException, resolveClass will throw a ClassNotFoundException containing the IllegalArgumentException inside it as source. This is because in most probable cases such an exception would result for ClassNotFoundException cases only. Since a proxy class never has its own serializable fields, the classdata[] in the stream representation of a proxy instance consists wholly of the instance data for its superclass, java.lang.reflect.Proxy. In most cases the only serializable field that a proxy has is ‘h’, which contains the invocation handler for the proxy instance.  

(with inputs from oracle.com, IBM developerworks and theserverside.com)

Advertisements

Leave a Reply

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out / Change )

Twitter picture

You are commenting using your Twitter account. Log Out / Change )

Facebook photo

You are commenting using your Facebook account. Log Out / Change )

Google+ photo

You are commenting using your Google+ account. Log Out / Change )

Connecting to %s

%d bloggers like this: