Tracking all instances of a class

In Diagnosing AWT thread issues, I made use of the fact that java.awt.Frame gives you access to all the extant frames. Last night, while adding a menu item to accept a spelling to JTextComponentSpellingChecker, I needed to do something similar because I needed a way to tell all spelling checkers to re-check their documents.

One way to do this would have been to have a static listener list and static add and remove methods. I didn't want to do this because I'm sick of writing listener list code and wanted to solve this problem once and for all, and because with no C++-like destructors in Java, removing yourself isn't as comfortable as I'd like it to be. One of the goals of my spelling checker (like most of my library code) is that the behavior should be as close to 'free' as possible. If it takes more than a single line to add all the spelling checking functionality to a JTextComponent, I would consider that a failure.

I thought I knew what I wanted: a mapping from Class to Set<WeakReference>, and one method to add a maplet, and another to get a list of the instances of a given class. I thought I'd check out Frame first, though, and see if there was anything I should be aware of.

There are three methods and one field involved. The methods add to, remove from, and return a copy of the list.

The first unusual aspect is the field that each Frame has:

transient private WeakReference weakThis;

This is the WeakReference that's kept in the list, and it's kept hold of by the instance so that Frame.finalize can remove it from the list so that it can be garbage collected. Not the Frame: that's fine; it's the WeakReference instance itself that could be leaked. Two weak references to the same object, it seems, are not equal. (I don't know why they didn't want to iterate over the list, invoking WeakReference.get and using ==.)

An unusual aspect of the implementation to my eyes is that the methods don't use the synchronized modifier. Why are the methods not synchronized? Because they're not static, so they wouldn't be synchronizing on anything useful. Why aren't they static? Because they access weakThis. One design decision forces another (although not really; it could always be passed as a parameter). Presumably for reasons of consistency, the getFrames method, which is static also uses a synchronized block rather than the synchronized modifier.

The really weird bit is getFrames. It has to filter out the weak references that now point to null. It does this by taking each instance from its list, and inserting it into a Frame[], and then copying the used part of that array into a new array of the right size. This is how we used to program, before Java got to be as fast as it is today. We used to worry about each and every allocation, and we used to use primitive arrays and System.arraycopy. To be honest, I'd almost forgotten!

Given that I can't imagine where this would sensibly be used for performance-critical code, I went with just an ArrayList, because that lets me say in 10 lines what Sun's code from the days of Java 1.2 took 35 lines to say. Being able to see an entire method at a glance is worth its weight in gold.

I toyed with the idea of having something you subclass if you want your class' instances to be tracked; it would have worked fine for the application I had in mind, but it wouldn't have been possible to use anything similar for Frame. It's usually best to avoid subclassing if you can, even in languages with multiple inheritance.

I'm also planning on waiting until leaking WeakReference instances becomes a problem before doing anything about it. But I don't want explicit removal. I'd rather have getInstancesOfClass use a proper Iterator and remove ones I find pointing to null. That, or have a daemon thread.

Anyway, here's my current general-purpose implementation, in its entirety:

package e.util;

import java.lang.ref.*;
import java.util.*;

* Lets you keep track of all the instances of a given class. Just add a call
* to InstanceTracker.addInstance to the class' constructor, and you can
* later use InstanceTracker.getInstancesOfClass to get a list of the instances
* that are still extant.
* @author Elliott Hughes
public class InstanceTracker {
private static final HashMap CLASS_TO_INSTANCES_MAP = new HashMap();

public static synchronized void addInstance(Object instance) {
ArrayList instances = instancesOfClass(instance.getClass());
instances.add(new WeakReference(instance));

private static synchronized ArrayList instancesOfClass(Class klass) {
ArrayList instances = (ArrayList) CLASS_TO_INSTANCES_MAP.get(klass);
if (instances == null) {
instances = new ArrayList();
CLASS_TO_INSTANCES_MAP.put(klass, instances);
return instances;

public static synchronized Object[] getInstancesOfClass(Class klass) {
ArrayList result = new ArrayList();
List weakReferences = instancesOfClass(klass);
for (int i = 0; i < weakReferences.size(); ++i) {
WeakReference weakReference = (WeakReference) weakReferences.get(i);
Object instance = weakReference.get();
if (instance != null) {
return result.toArray(new Object[result.size()]);

private InstanceTracker() {

This is now part of the library available from my home page. As is the JTextComponent spelling checking.