2009-10-05 6 views
0

Вот некоторые примеры кода, чтобы проиллюстрировать наш вопрос:Присвоение значения при возникновении исключения (Java)

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

Вопрос заключается в том, что значение «а», как напечатано в конце концов блок ...

Я не уверен, и я думаю, что наткнулся на то, что не может быть полностью описано. Я наблюдал на своем ноутбуке (jdk1.6.0.16 на x86), что «a» равно A(). Однако с JDK 1.4 на Solaris я считаю, что значение равно null (например, если присваивание выполнялось даже при исключении исключения). Это, очевидно, связано с ошибкой, и мы будем развертывать версию без назначения только для того, чтобы убедиться, но мы хотели бы знать, заметил ли кто-то из вас это или предложил какое-то объяснение.

Мы также сделаем пример программы, чтобы продемонстрировать это на проблемном JDK ... и мы опубликуем результаты.

ответ

0

Если оптимизатор может убедиться, что new A() не имеет побочных эффектов, он оптимизирует первое задание. Чтобы изолировать этот случай, отключите JIT и запустите код еще раз. Если после этого произойдет a != null, вы увидите сбой оптимизатора.

Очевидным исправить это больше new A() перед try блока:

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

@Aaron:. Новый A() в исходном коде не могут быть оптимизированы в сторону, так как в результате объект используется в некоторых исполнениях –

+0

Почему комментарий Аарона вниз проголосовали ничего не делается? с исходной ссылкой «A», и, конечно же, возможно, что JIT (на Solaris JDK 1.4) просто NOPs это прочь. В этом случае блок finally увидит нуль. – alphazero

3

Назначение должно определенно не произойти, когда происходит исключение - это было бы очень серьезной ошибкой в ​​JVM. Но сначала я подозреваю, что исключение фактически происходит где-то в другом месте (такое в конструкторе A()).

2

Я бы предположил, что a == new A(), если он не оптимизирован. Не код немного глупо выглядит как:

a=1; 
a=2; 

Может переписать в намереваются ваш код:

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

Вы могли бы попытаться скомпилировать код, то глядя на байткоде, чтобы увидеть, что происходит на. Я использую байткода Структуризатор затмение плагин от http://andrei.gmxhome.de/eclipse/

1

Просто сделал тест на Solaris с Sun JDK_1.4.2_05 на Solaris со следующей программой

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(); 
    } 
} 

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

+0

Ну, это должно быть довольно легко подтвердить где именно исключение выбрано - просто посмотрите на его стек трассировки. –

0

Я также запускал код на Solaris 10 с JDK 1.4.2, и он имел правильное поведение. Проблема заключалась в том, что код в производстве не был тем, на который я смотрел ... (предыдущая версия)

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

Умственная нота в следующий раз: «Во-первых, проверьте очевидное: если у вас странное поведение, код, который вы выполняете, может быть не тем, что было выполнено."

Еще раз спасибо, Седрик

Смежные вопросы