views:

16

answers:

1

When debugging Java code, Eclipse has a feature that allows it to find all instances of a given type (via context menu in the Variables window). Is there any way to filter these programatically? For instance, I want all instances of class FieldInstruction where

the_instance.getType().getName().equals("somestring")  

Evaluates to true.

As I am trying to debug code that is already supposed to be enumerating all the instances, just creating my own code the walk the tree structure where the classes exist kind of defeats the purpose. I'd really like to be able to do this filtering through the Display or Expressions windows.

A: 

I ended up creating a rather hacky "InstanceRegistry" class. In the constructor of each class type I want to track, I put

InstanceRegistry.register(this);

This even takes care of "registering" the instance under all super classes and interfaces.

To iterate over the instances (can even be done in the Eclipse Display window):

for(Object instance : InstanceRegistry.getInstances(FieldInstruction.class)) {
    //do something
}

The source code of class InstanceRegistry:

import java.lang.ref.WeakReference;
import java.util.HashMap;
import java.util.HashSet;
import java.util.Iterator;

public class InstanceRegistry {
    private InstanceRegistry() {}

    private static HashMap<Class<?>, HashSet<WeakReference<?>>> instances = new HashMap<Class<?>, HashSet<WeakReference<?>>>();

    public static <T> Iterable<T> getInstances(final Class<T> type) {
        return new Iterable<T>() {
            public Iterator<T> iterator() {
                return new Iterator<T>() {
                    Iterator<WeakReference<?>> it = instances.get(type).iterator();
                    T item = find();

                    {
                        System.gc();
                    }

                    public boolean hasNext() {
                        return item != null;
                    }

                    private T find() {
                        WeakReference<T> fi;
                        while(it.hasNext()) {
                            fi = (WeakReference<T>) it.next();
                            if(fi.get() != null)
                                return fi.get();
                        }
                        return null;
                    }

                    public T next() {
                        T ret = item;
                        item = find();
                        return ret;
                    }

                    public void remove() {
                        throw new UnsupportedOperationException();
                    }
                };
            }
        };
    }

    private static void put(Class<?> type, WeakReference<?> instance) {
        HashSet<WeakReference<?>> list = instances.get(type);
        if(list == null) {
            list = new HashSet<WeakReference<?>>();
            instances.put(type, list);
        }
        list.add(instance);
    }

    public static void register(Object instance) {
        WeakReference<Object> inst = new WeakReference<Object>(instance);
        Class<?> c = instance.getClass();
        do {
            put(c, inst);
            for(Class<?> ci : c.getInterfaces()) {
                put(ci, inst);
            }
            c = c.getSuperclass();
        } while(c != Object.class);
    }
}
Joshua Warner