Dynamic Proxies are a fantastic tool to have in your kit, and pretty easy to get up and running with.

A Dynamic Proxy is just what the name suggests: a proxy to a "normal" Java class, where the proxy is created dynamically - at runtime - and can be substituted instead of the proxied class.

If that still doesn't make sense, hopefully the example below will clear it up.

Lets imagine we want to be able to time the execution of any method on any implementation of any interface. We don't know or care what the interface is. We'll do this by passing the class that implements the interface to an "InstrumentationService", whose interface looks like this:

public interface InstrumentationService {
    /**
     * @param aT - the object to be instrumented for monitoring
     * @return A polymorphically equivalent T which has been instrumented
     */
    public <T> T instrument(T aT);
}

We'll get to the implementation of InstrumentationService shortly, but for now it should be clear that to instrument a class is as simple as this:

private InstrumentationService instr;

public void doSomeStuff() {
    SomeInterface _si = new SomeClassThatImplementsIt();

    _si.doSomething(); // won't be timed

    _si = instr(_si);

    _si.doSomething(); // will be timed!
}

OK, so how can we implement InstrumentationService so that it can decorate arbitrary methods on as-yet-unknown interfaces? Enter Dynamic Proxies.

There are several rules and caveats to follow which I won't go into - they are documented pretty well here. For now it should suffice to say that you can only proxy interfaces (which is ok because you always program to interfaces / design by contract anyway, right?)

Here's an implementation of InstrumentationService that uses Dynamic Proxying:

package com.sjl.example;

import java.lang.reflect.*;
import java.util.*;
import java.util.concurrent.*;

public abstract class DynamicInstrumentationService 
implements InstrumentationService {

    protected abstract void record(String anEvent, long aNanos);

    @SuppressWarnings("unchecked")
    @Override
    public <T> T instrument(final T aT)
    {
        return (T) Proxy.newProxyInstance(
            aT.getClass().getClassLoader(), 
            aT.getClass().getInterfaces(), 
            new InvocationHandler() {
                @Override
                public Object invoke(
                    Object aProxy, Method aMethod, Object[] aArgs) 
                    throws Throwable 
                {
                    long _start = System.nanoTime();
                    try {
                        return aMethod.invoke(aT, anArgs);
                    } catch (InvocationTargetException anExc) {
                        throw anExc.getCause();
                    } finally {
                        record(_t.event(), System.nanoTime()-_start);
                    }
                }
            });
    }
}

So what do we have here?

  1. An abstract implementation of IntrumentationService which defers the actual recording of the timed value to a concrete subclass - you could extend and implement the record method to log to stdout, for example.
  2. The instrument method creates a new Dynamic Proxy around the given class by invoking Proxy.newInstance. Notice that we use the classloader of the given class, and pass all of the interfaces it implements as types to be proxied.
  3. The details of what to do when any method of the proxy is invoked are in the InvocationHandler, implemented here as an anonymous inner class. Its pretty simple - capture the clock time before the method is invoked; invoke the method; capture the clock time after the method completes; record the difference in time (after - before).

Notice that when we invoke the proxied class's method, we wrap the invocation with a try/catch that catches InvocationTargetException, and if such an exception is thrown we propagate its cause, not the InvocationTargetException itself. This is just unwrapping an uninteresting layer of exceptions (which we added by using reflection to invoke the method) to get to the real problem.

This is a pretty simple example of what you can do with Dynamic Proxies. Even with this simple example its clear that you could modify it to, for example, record separate timings for successful invocations vs those that throw exceptions, or to only record timings for methods with annotations (e.g. you might create an @Timed annotation), etc., etc.

I should mention that there is a down-side to Dynamic Proxies: they use reflection to invoke the method of the proxied class, so there is a small performance penalty.

Lately I've been having all kinds of fun with Dynamic Proxies, from instrumentation (somewhat more complex than the above example) to monitoring service health (by escalating through warning statuses based on the ratio of successful/exceptional completion).

My favourite use so far: asynchronous execution of synchronous service calls, returning the result as a disguised/implicit Future/Promise with a coordinated Service Level Agreement cut-off . . . yeah anyways, that's a blog post for another day :) (update 09-09-2012: see Implicit-Futures)

blog comments powered by Disqus