Does return "happen after" finally?

Justin picture Justin · Apr 18, 2011 · Viewed 12.2k times · Source

I am trying to convince myself that actions taken in the finally clause happen before the function return (in the memory consistency sense). From the JVM specification, it is clear that within a thread, program order is supposed to drive the happens before relationship -- if a happens b in the program order then a happens before b.

However, I have not seen anything explicitly stating that finally happens before return, so does it? Or, is there some way that the compiler could reorder the finally clause since it is simply logging.

Motivating example: I have one thread fetching objects out of a database and am putting them into an ArrayBlockingQueue, and another thread is taking them out. I have some try- finally blocks for event timing, and I am seeing after affects of the return before the log statement

Thread 1:

public Batch fetch() {
    try {
        log("fetch()+");
        return queryDatabase();
    }
    finally {
        log("fetch()-");
    }
     ...
    workQueue.put(fetch());

Thread 2:

log("take()+");
Batch b = workQueue.take();
log("take()-");

To my great surprise this prints out in an unexpected order. While, yes, logging statements in different threads can appear out of order, there is a time difference of at least 20 ms.

124 ms : take()+
224 ms : fetch()+
244 ms : take()-
254 ms : fetch()-

Note this is not exactly the same question as does finally trump return. I'm not asking what will be returned, but instead about memory consistency and execution order.

Answer

David Heffernan picture David Heffernan · Apr 18, 2011

The call to queryDatabase() happens first. Then the finally block. Then control leaves the function (that's the return).