Alex Rivera | Logout

Why are there finalizers in java and c#?

Asked 2009-12-05T01:24:43.223
11

I'm not quite understanding why there are finalizers in languages such as java and c#. AFAIK, they:

  • are not guaranteed to run (in java)
  • if they do run, they may run an arbitrary amount of time after the object in question becomes a candidate for finalization
  • and (at least in java), they incur an amazingly huge performance hit to even stick on a class.

So why were they added at all? I asked a friend, and he mumbled something about "you want to have every possible chance to clean up things like DB connections", but this strikes me as a bad practice. Why should you rely on something with the above described properties for anything, even as a last line of defense? Especially when, if something similar was designed into any API, said API would get laughed out of existence.

Edit
Report

3 Answers

10

Hmya, you are getting a picture painted here that's a bit too rosy. Finalizers are not guaranteed to run in .NET either. Typical mishaps are a finalizer that throws an exception or a time-out on the finalizer thread (2 seconds).

That was a problem when Microsoft decided to provide .NET hosting support in SQL Server. The kind of application where restarting the app to solve resource leaks isn't considered a viable workaround. .NET 2.0 acquired critical finalizers, enabled by deriving from the CriticalFinalizerObject class. The finalizer of such a class must adhere to the rulez of constrained execution regions (CERs), essentially a region of code where exceptions are suppressed. The kind of things you can do in a CER are very limited.

Back to your original question, finalizers are necessary to release operating system resources other than memory. The garbage collector manages memory very well but doesn't do anything to release pens, brushes, files, sockets, windows, pipes, etc. When an object uses such a resource, it must make sure to release the resource after it is done with it. Finalizers ensure that happens, even when the program forgot to do so. You almost never write a class with a finalizer yourself, operating resources are wrapped by classes in the framework.

The .NET framework also has a programming pattern to ensure such a resource is released early so the resource doesn't linger around until the finalizer runs. All classes that have finalizers also implement the IDisposable.Dispose() method, allowing your code to release a resource explicitly. This is often forgotten by a .NET programmer but that doesn't typically cause problems because the finalizer ensures it will eventually be done. Many .NET programmers have lost hours of sleep worrying whether or not all Dispose() calls are taken care of and massive numbers of threads have been started about it on forums. Java folks must be a happier lot.


Following

answered 2009-12-05T02:17:25.440
4

If you read the JavaDoc for finalize() it says it is "Called by the garbage collector on an object when garbage collection determines that there are no more references to the object. A subclass overrides the finalize method to dispose of system resources or to perform other cleanup."

http://java.sun.com/javase/6/docs/api/java/lang/Object.html#finalize

So that's the "why". I guess you can argue whether their implementation is effective.

The best use I've found for finalize() is to detect bugs with freeing pooled resources. Most leaked objects will get garbage collected eventually and you can generate debug information.

class MyResource {
    private Throwable allocatorStack;

    public MyResource() {
        allocatorStack = new RuntimeException("trace to allocator");
    }

    @Override
    protected void finalize() throws Throwable {
        try {
            System.out.println("Bug!");
            allocatorStack.printStackTrace();
        } finally {
            super.finalize();
        }
    }
 }
answered 2009-12-05T01:42:32.110
0

In .Net land, t is not guaranteed when they run. But they will run.

answered 2009-12-05T01:31:14.173

Your Answer