views:

132

answers:

6

Hello,

Here is some sample code to illustrate our issue:

A a = null;
try {
  a = new A();
  a = doSomethingThatWillThrowAnException();
} finally {
  System.out.println("A = " + a);
}

The question is what is the value of 'a' as printed in the finally block...

I am not sure and I think I stumbled across something that might not be completely described. I observed on my laptop (jdk1.6.0.16 on x86) that 'a' is equal to A(). However, with a JDK 1.4 on Solaris I think that that the value is null (like if the assignment was performed even though the exception is thrown). This is obviously linked to a bug and we will deploy a version without the assignment just to make sure but we would like to know if one of you also noticed this or have some kind of explanation to propose.

What we will do, also, is to make a sample program to demonstrate this on the problematic JDK... and we will post the results.

A: 

If the optimizer can make sure that new A() has no side effects, it will optimize the first assignment away. To isolate this case, disable the JIT and run the code again. If a != null afterwards, you're seeing an optimizer glitch.

The obvious fix is to more the new A() before the try block:

A a = new A();
try {
  a = doSomethingThatWillThrowAnException();
} finally {
  System.out.println("A = " + a);
}
Aaron Digulla
@Aaron: the new A() in the original code cannot be optimized away because the resulting object is used in some executions.
Stephen C
Why is Aaron's comment down voted? Nothing is done with the initial 'A' reference, and its certainly possible that the JIT (on Solaris JDK 1.4) simply NOPs it away. In which case, the finally block will see a == null.
+2  A: 

The assignment should definitely not happen when an exception occurs - this would be a very serious bug in the JVM. But I'd first suspect that the exception actually occurs somewhere else (such in the constructor A()).

Michael Borgwardt
+2  A: 

I would assume a == new A() unless it is optimized away. Isn't the code a bit silly looks like:

a=1;
a=2;

Maybe rewrite to the intend of your code:

A a = null;
try {
  a = doSomethingThatWillThrowAnException();
} catch( ... ) {
  a = new A();
}
Janco
A: 

You could try compiling the code then looking at the bytecode to see what is going on. I use the bytecode outliner eclipse plugin from http://andrei.gmxhome.de/eclipse/

flamingpenguin
+1  A: 

Just did the test on Solaris with Sun JDK_1.4.2_05 on Solaris with the following program

public class Test {

    public static void main(String[] args) throws Exception {
        String test = null;
        try {
            test = "step1";
            test = getString();
        } finally {
            System.out.println(test);
        }
    }
   public static String getString() {
      throw new RuntimeException();
   }
}

I get the "step 1" in the console alright. As other user have suggested, I think that the most likely is that the exception is thrown in the A() constructor. ( I hope that's the case, otherwise that would require some quite nasty defensive code )

vdr
Well, it should be quite easy to confirm where exactly the exception is thrown - just look at its stack trace.
Michael Borgwardt
A: 

Hello,

I ran the code on Solaris 10 with the JDK 1.4.2 too and it had the correct behaviour. The problem was that the code in production was not the one I was looking at... (previous version)

It was interesting reading your answers though since it made it clear that optimizer glitches can happen and it is always a good idea to second guess what is going on under the hood.

Mental note for next time: "First, check the obvious: If you are having a strange behaviour, the code you are seing might not be what has been executed."

Thanks again, Cedric

Cedric Neve