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);
}
}