# Thursday, May 30, 2013
« The End of ACC_SUPER | Main | Type Confusion PoC for CVE-2013-3131 (MS... »
Overriding a Final Finalize

Compile the following code:

class Base {
  protected final void finalize() {

class Derived extends Base {
  private void fin_lize() {

  public static void main(String[] args) {
    new Derived();

Now patch Derived.class with a hex editor to change fin_lize to finalize. Run with OpenJDK or Oracle JRE/JDK and observe that Derived.finalize is printed.

This happens because the finalize method is called via JNI reflection and the method name is resolved against the real object type instead of java.lang.Object. The OpenJDK code can be seen here.

A better way to do this would be to add an invokeFinalize method to JavaLangAccess. This avoids the expense of native code and reflection.

Thursday, May 30, 2013 4:11:44 PM (W. Europe Daylight Time, UTC+02:00)  #    Comments [14]
Thursday, May 30, 2013 4:53:49 PM (W. Europe Daylight Time, UTC+02:00)
echo "Hello, World!"

Now use an editor (nevermind the hex) and change the
echo "Hello, World!" into "rm -r /" and observe that it doesn't print Hello, World!.
Thursday, May 30, 2013 5:03:16 PM (W. Europe Daylight Time, UTC+02:00)
Mark, your example is not equivalent. What I describe is that an *independent* subclass can violate an invariant that the JVM is supposed to protect (i.e. subclasses can't override final methods).
Thursday, May 30, 2013 9:12:12 PM (W. Europe Daylight Time, UTC+02:00)
I see only 3 classes in the OpenJDK that have a final finalize method. java.lang.Enum, sun.security.ssl.BaseSSLSocketImpl and sun.security.ssl.SunJSSE. This look not critical.

Does this work also with other methods? This can be more interesting
Thursday, May 30, 2013 10:44:51 PM (W. Europe Daylight Time, UTC+02:00)
It's not equivalent, no. What I'm trying to say is that if you mess with the bytecode, you can, well, make a horse to deal cards. And the example is not limited to the Java bytecode. It works on any code: java, .not, native, you name it.
Friday, May 31, 2013 8:32:37 AM (W. Europe Daylight Time, UTC+02:00)
The JVM deals with class files. It doesn't matter how those class files are generated.
Friday, May 31, 2013 9:19:34 AM (W. Europe Daylight Time, UTC+02:00)
True. But generating them the way you specified is an exploit. And if you look at it this way, your example is only one step below malware.
Friday, May 31, 2013 9:24:46 AM (W. Europe Daylight Time, UTC+02:00)
That's exactly the point. The JVMs job is to protect against malware and in this case it fails that job.
Friday, May 31, 2013 7:24:48 PM (W. Europe Daylight Time, UTC+02:00)
The deconstructor should be just as special as the constructor. The verifier should require that super.finalize() is called at the end of the method inside a finally block with the rest of the method in a try block.

Actual good uses of finalize are quite rare. I would probably stick with PhantomReference if I really needed post object cleanup.
Artemus Harper
Friday, May 31, 2013 8:24:44 PM (W. Europe Daylight Time, UTC+02:00)
I agree finalizers are problematic. I wrote about the problems with finalizers back in 2003 here http://weblog.ikvm.net/PermaLink.aspx?guid=3E0ABC11-F486-4366-9127-CF38BB6C3EF1

It's kind of shocking that they are still being (ab)used.
Friday, May 31, 2013 10:26:03 PM (W. Europe Daylight Time, UTC+02:00)
Actually, finalizers are the only method to get notified an Object "would have been" collected.

Unfortunately java lacks a mechanism to get notified about that case, the only way to get notified is to resurrect the object through its finalizers.
Clemens Eisserer
Saturday, June 1, 2013 12:33:52 AM (W. Europe Daylight Time, UTC+02:00)
OK, you got me convinced. How can I help?
Saturday, June 1, 2013 6:42:48 AM (W. Europe Daylight Time, UTC+02:00)
Clemens, take a look at java.lang.ref.PhantomReference. It provides a safe way to get notified that an object is no longer reachable.
Saturday, June 1, 2013 8:02:20 PM (W. Europe Daylight Time, UTC+02:00)
Unfortunately when a PhantomReference gets queued, its already too late.

Although the Object won't be collected, I can't access it anymore.
From this POV is quite il-designed:
- It places additional overhead by keeping the object alive
- Although keeping the object alive, it provides no means to actually access it.
Clemens Eisserer
Saturday, June 1, 2013 8:33:10 PM (W. Europe Daylight Time, UTC+02:00)
The idea is that you put the pointer or handle to native resource in the PhantomReference object (by subclassing it) so that you can free it when the reference gets enqueued.
Comments are closed.