views:

310

answers:

3

This

public class test 
{
    public static void main(String[] args) 
    {
        Object o = null;
        assert o != null;
        if(o != null)
          System.out.println("o != null");
    }
}

prints out "o != null"; both 1.5_22 and 1.6_18. Compiler bug? Commenting out the assert fixes it. The byte code appears to jump directly to the print statement when assertions are disabled:

 public static main(String[]) : void
   L0
    LINENUMBER 5 L0
    ACONST_NULL
    ASTORE 1
   L1
    LINENUMBER 6 L1
    GETSTATIC test.$assertionsDisabled : boolean
    IFNE L2
    ALOAD 1: o
    IFNONNULL L2
    NEW AssertionError
    DUP
    INVOKESPECIAL AssertionError.<init>() : void
    ATHROW
   L2
    LINENUMBER 8 L2
    GETSTATIC System.out : PrintStream
    LDC "o != null"
    INVOKEVIRTUAL PrintStream.println(String) : void
   L3
    LINENUMBER 9 L3
    RETURN
   L4
A: 

I don't know about "nasty". Can you give a real example of some code where this would bite you? Your example looks very contrived.

EDIT - out of curiosity, I typed in the program, compiled it and ran it with java 1.6.0_16. No compiler bug is evident for me:

  • With assertions enabled (java -ea test) I get an assertion error.
  • With assertions disabled (java test) I get no output.
Stephen C
I'd argue that any bug that makes the compiler generate code that silently does the wrong thing is "nasty". (A less nasty compiler bug would be if the compiler actually failed to compile such code -- then at least you know something is wrong.)
Laurence Gonsalves
Thanks for testing. Just tried, does not happen with jdk1.6.0_18 for me either. Now I just need to figure out what's different with the way Eclipse builds it ...
Alex
@Alex Eclipse has its own compiler.
Tom Hawtin - tackline
A: 

The JVM is optimising the if (o != null) clause away because you've already asserted that o is never going to be null.

Assertion are not enabled by default at runtime, and are generally used to validate that code fulfils some contract, e.g. you just want to make sure that a certain object is never going to be null (e.g. to avoid null pointer exceptions). It is because of that "contract" that the compiler can optimise the if (o != null) away, because it knows that this condition will never happen.

As they are generally not enabled at runtime, think of them as helping to develop a piece of code rather than a runtime error checking mechanism.

beny23
Can you point out the section of the JLS that says that the compiler may assume assertions are true when optimizing?
Laurence Gonsalves
Nope. Combined with the other answers that cannot replicate the behaviour and the fact I didn't try it myselve, I'm tempted to believe that it might have been a compiler bug but some overzealous optimisation could have been the cause...
beny23
Considering that the code only appears to occur when built with the Eclipse compiler, maybe the Eclipse compiler is optimising the if statement away?
beny23
A: 

Assertions can be enabled and disabled at runtime. If you execute your code with the -ea-switch (for enable assertions) the assert should work:

java -ea my.class
Mnementh