Garbage Collecting Threads

During the work on my master thesis, I found myself sitting and running Java simulations on a implementation of a database model. The implementation had one worker thread (anonymous enclosed class extending java.lang.Thread) running in the background and made callers to the model wait for different times depending on load and such. What I then realised after running a long simulation involving several instances of the model implementation was that they all stay in memory.

The program I wrote made hundreds of calls to a method which started by instantiating the model implementation. When that experiment was done, it released the reference to the model object by simply returning. This meant the worker thread would still be running in the background.

One of the nice features in Java is that objects without any references to them are cleaned away by the Java Garbage Collector (GC). The GC starts from all running threads and sees which objects it can reach. Non-reachable objects are safe to clean away.

But since my worker thread was running in the background, the GC could not clean away my old instances of the model implementation. Also, making the worker thread a daemon thread was one thought, but that doesn’t affect the GC, only the ending of a Java program.

The solution I found was in the package java.lang.ref. The WeakReference class holds a reference to an object. But the weak reference doesn’t stop the GC from cleaning the object away. In other words, if an object can only be reached through a chain of references were at least one is weak, then the object is weakly reachable, and clean away that object. Atomically, at the same time, all weak references to that object will be set to null.

So, it was only a matter of extracting the worker thread from the model implementation, making it a normal class, giving it a weak reference to the model implementation and checking whether the reference is null before using it. Also, it is important to remove all references to the model implementation as soon as you are done with them, because hard references prevent the object from being cleaned away.

Some Java code… Both classes can be en the same file, Database.java.

public class Database {
    void updateStatesAndStuff() {
        // ...
    }
}
 
private class WorkerThread extends Thread {
    WeakReference<Database> dbRef = ...;
 
    public void run() {
        while (true) {
            Database db = dbRef.get();
 
            if (db == null)
                // Object has been cleaned away! Stop thread
                return;
 
            db.updateStatesAndStuff();
 
            // Remove hard reference, allowing it to be cleaned away
            db = null;
 
            // Sleep until it's time to update again
            timingAndSleep();
        }
    }
}
This entry was posted in Coding and tagged , , , , . Bookmark the permalink.

Leave a Reply

Your email address will not be published. Required fields are marked *