2009-04-13

Finalizers considered harmful

I diagnosed an interesting problem at work recently; our application, when running on some enterprise platforms was eventually (over a number of days) running out of memory, grinding to a halt then fatally OutOfMemoryErroring, regardless of how much heap it was given.

Eclipse Memory Analysis Tool (via. DTFJ for the IBM heapdumps) is rather resource hungry, needing massively increased the heap (~7gb, i.e. can't be run on an 32-bit machine) and stack size (~8mb). However, once the heap dump had been loaded (1h+), it was reasonably obvious (after #266231) what was happening:

The finalizers wern't being processed fast enough.

The finalization thread is run at a lower priority, and, seemingly, on the configurations on these machines/OS/JVM combinations, it was getting no time at all.

For historical reasons, quite a few large classes in our codebase have:

void finalize() {}

..in, that is, finalizers that do nothing at all. These empty finalizers still have to be run before the object can be collected, however, so they simply wern't, quickly leaking memory. The more that was leaked, the slower the JVM was running, so the less time the finalization thread had, a vicious cycle.

I couldn't find many other people experiencing this on the internet, I can only assume that people simply don't use finalizers, which can only be a good thing.

One guy had a rather more interesting solution:

public static void main(String[] args)
{
  new Object()
  {
    @Override protected void finalize() throws Throwable
    {
      super.finalize();
      Thread.currentThread().setPriority(Thread.MAX_PRIORITY);
    }
  };
  // ...
}

The worst thing is, I can't really see any disadvantages to this...


Commenting is disabled for this post.

Read more of Faux' blog