2010-02-17 3 views
4

ЭтоJava утверждает неприятный побочный эффект - ошибка компилятора?

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

печатает "о = нуль!"; как 1.5_22, так и 1.6_18. Ошибка компилятора? Комментируя утверждение, он исправляет это. Байт-код появляется, чтобы перейти непосредственно к утверждению печати, когда утверждения отключены:

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 
+0

ничего не печатает здесь, 1.6.0_12 – Bozho

+0

Какой версии JAVAC компилятора вы использовали для компиляции? Это должна быть ошибка компилятора, компиляция с 1.6.0_18 (оконным 32-битным) кодом работает как ожидалось (не печатает o! = Null). –

+0

Не воспроизводимый. Вы уверены, что это именно ваш тестовый код? Какой компилятор и какой jvm вы используете? Какие флаги? – Avi

ответ

1

Я не знаю, о «противный». Можете ли вы дать реальный пример некоторого кода, где это вас укусит? Ваш пример выглядит очень надуманным.

EDIT - Из любопытства я набрал программу, скомпилировал ее и запустил с помощью java 1.6.0_16. Для меня не видно ошибки компилятора:

  • С включенными утверждениями (java -ea test) Я получаю сообщение об ошибке утверждения.
  • С утверждениями отключены (тест java) Я получаю нет выход.
+1

Я бы утвердил, что любая ошибка, которая заставляет компилятор генерировать код, который молча делает неправильную вещь, является «противным». (Менее неприятная ошибка компилятора была бы в том случае, если компилятор действительно не смог скомпилировать такой код - тогда, по крайней мере, вы знаете, что что-то не так.) –

+0

Спасибо за тестирование. Просто попробовал, для меня тоже не случилось с jdk1.6.0_18.Теперь мне просто нужно выяснить, что отличаетс тем, как Eclipse создает его ... – Alex

+6

@Alex Eclipse имеет свой собственный компилятор. –

0

JVM оптимизирует предложение if (o! = Null), потому что вы уже утверждали, что o никогда не будет null.

Утверждение не включено по умолчанию во время выполнения и обычно используется для проверки того, что этот код выполняет какой-либо контракт, например. вы просто хотите удостовериться, что определенный объект никогда не будет нулевым (например, чтобы исключить исключения нулевого указателя). Именно из-за этого «контракта» компилятор может оптимизировать if (o! = Null), потому что он знает, что это условие никогда не произойдет.

Поскольку они, как правило, не включены во время выполнения, считают их полезными для разработки фрагмента кода, а не механизма проверки ошибок во время выполнения.

+1

Можете ли вы указать раздел JLS, в котором говорится, что компилятор может считать утверждения истинными при оптимизации? –

+0

Нет. В сочетании с другими ответами, которые не могут воспроизвести поведение, и тот факт, что я не пробовал его myselve, я склонен полагать, что это может быть ошибка компилятора, но может быть причиной некоторой чрезмерной оптимизации. – beny23

+0

Учитывая, что код появляется только при построении с помощью компилятора Eclipse, возможно, компилятор Eclipse оптимизирует оператор if? – beny23

1

Утверждения могут быть включены и отключены во время выполнения. Если выполнить код с -EA-переключателем (для включения утверждений) утверждает должно работать:

java -ea my.class 
Смежные вопросы