Why is the finalize() method in java.lang.Object "protected"?

Solution 1:

I answer your question with another question:

Why finalize method shouldn't be protected?

In general, you should try to keep things as much private as possible. That's what encapsulation is all about. Otherwise, you could make everything public. finalize can't be private (since derived classes should be able to access it to be able to override it), so it should at least be protected but why give out more access when it's not desirable?


After reading your comment more carefully, I guess I see your main point now. I think your point is since everything derives from java.lang.Object and consequently accesses its protected members, it wouldn't make any difference for it (or any method in java.lang.Object for that matter) to be public as opposed to protected. Personally, I'd count this as a design flaw in Java. This is indeed fixed in C#. The problem is not why finalize is protected. That's OK. The real issue is that you shouldn't be able to call protected methods in the base class through an object reference of the base class type. Eric Lippert has a blog entry discussing why allowing such kind of access to protected members is a bad idea which is further elaborated on Stack Overflow in this question.

Solution 2:

Why is the finalize() method's access modifier is made as protected. Why cant it be public?

It is not public because it shouldn't be invoked by anyone other than the JVM. However, it must be protected so that it can be overridden by subclasses who need to define behavior for it.

If i call it twice in my program, internally what is happening?

You can call it all you want, its just a method after all. However, much like public static void main(String [] args), it has special meaning to the JVM

Will the garbage collector call this again?

Yes

Solution 3:

  • finalize is meant to be called by the gc only and as such does not require public access
  • finalize is guaranteed to be called only once by the gc, calling it yourself will break this guarantee, as the gc wont know about it.
  • Any overriding class can make finalize public, which I believe is bad for the above reasons
  • finalize should not contain much code, as any exception thrown by finalize may kill the finalizer thread of the gc.

Rant against finalize()

  • Managing native resources or any resource which requires dispose() or close() to be called may cause hard to find bugs as they will only be released when the jvm runs out of memory, you should release resources manually. Finalize should only be used for debugging resource leaks or for cases where managing resources manually is too much work.
  • finalize will be called in an additional thread of the gc and may cause problems with resource locking and so on.
  • the reference classes like WeakReference and ReferenceQueue are an alternative (rather complex) way to deal with cleanup and may have the same problems as finalize() for native resources.

Beware of errors in the above statements, I'm a bit tired :-)