Yesterday I talked about how you can use WeakReference to allow a resource to be garbage collected even if it is referenced by another object, a JMX MBean in the case in question. In fact, you can use dynamic proxies to provide a more general framework for this sort of situation.

In the specific situation I was discussing before, you have aresource such as a cache, that may be garbage collected when it is no longer referenced. And you have a controllersuch as a JMX MBean that references the resource. But you don't want this reference to stop the resource from being garbage collected.

We can generalize this as follows:

  • The resource is defined by some Java interface,Cache in our example. Yesterday Cache was a concrete class, but for the technique we're talking about here it must be an interface, typically with a concrete class likeCacheImpl that provides its implementation.
  • Some references to the resource are weak, meaning that they should not prevent the resource from being garbage collected.
  • If the resource is garbage collected, and these weak references try to use it, we want to be able to define what happens. This might just be to throw an exception, or it might be take an action such as unregistering an MBean.

Dynamic proxies are an enormously useful feature of the Java platform once you understand what they are for. Suppose you have a Java interface, like Cache. A dynamic proxy allows you to produce a Java object that implements that interface. Every time someone calls one of the interface's methods on this object, the following method from the InvocationHandler interface is called to handle it:

public Object invoke(Object proxy,
                     Method method,
                 Object[] args) throws Throwable;

The method parameter allows you to know which method of the interface was called, and the argsparameter allows you to know what arguments it was called with. (The proxy argument is usually ignored.)

Inside invoke, you can do whatever's appropriate. You can create a handler that always throws an exception, to produce a dummy implementation of an interface that checks error behaviour for example. You can create a handler that logs the method call or performs security checks before reinvoking the sameMethod on another object.

It is this second kind of possibility that interests us here. If the WeakReference is still valid, then we just want to invoke the same method on the resource. If it's not valid, then we want to invoke the user-supplied missingHandlerinstead.

Suppose the Cache interface looks like this:

public interface Cache {
    public int dropOldest(int n);

Suppose we create a dynamic proxy for this interface, like this:

InvocationHandler handler = new SomeInvocationHandler(...);
Cache proxy = (Cache) Proxy.newProxyInstance(<...stuff...>, handler);

Then when we later call proxy.dropOldest(5), this will result in a call to

handler.invoke(proxy, method, new Object[] {5});

where method is ajava.lang.reflect.Method representing the methodCache.dropOldest(int).

What we want handler.invoke to do is to call this same Method on the resource, assuming it still exists, and otherwise run the user-suppliedmissingHandler.

Putting this all together, we get this:

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

public class WeakProxy {
    public static <T> T make(T resource,
                 Class<T> interfaceClass,
                 Callable<Object> missingHandler) {
    Handler handler = new Handler<T>(resource, missingHandler);
    Object proxy = Proxy.newProxyInstance(interfaceClass.getClassLoader(),
                          new Class[] {interfaceClass},
    return interfaceClass.cast(proxy);

    private static class Handler<T> implements InvocationHandler {
    Handler(T resource, Callable<Object> missingHandler) {
        this.resourceRef = new WeakReference<T>(resource);
        this.missingHandler = missingHandler;

    public Object invoke(Object proxy, Method method, Object[] args)
        throws Throwable {
        T resource = resourceRef.get();
        if (resource == null)
        return method.invoke(resource, args);

    private final WeakReference<T> resourceRef;
    private final Callable<Object> missingHandler;

The type parameter <T> to WeakProxy.makeallows us to specify that the resource parameter must implement the interface specified by theinterfaceClass parameter, and that the result ofWeakProxy.make also implements this interface.

In our example of a CacheControlMBean, we could use this class as follows:

    Cache cache = new CacheImpl();  // or whatever
    Cache weakCache =
        WeakProxy.make(cache, Cache.class, exceptionWhenMissingHandler);
    CacheControlMBean cc = new CacheControl(weakCache);
    ObjectName on = ...;
    mbeanServer.registerMBean(cc, on);

    private static final Callable<Object> exceptionWhenMissingHandler =
    new Callable<Object>() {
        public Object call() {
        throw new IllegalStateException("Object no longer exists");

With some more work, we could have the WeakProxyclass create a thread that calls the missingHandler as soon as the resource is garbage-collected, rather than waiting for somebody to call the proxy. The code would look something like the final version of the CacheControl MBean I posted before.