Присвоение значения при возникновении исключения (Java) - PullRequest
1 голос
/ 05 октября 2009

Вот пример кода, иллюстрирующий нашу проблему:

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

Вопрос в том, каково значение 'a', как показано в блоке finally ...

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

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

Ответы [ 6 ]

4 голосов
/ 05 октября 2009

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

2 голосов
/ 05 октября 2009

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

a=1;
a=2;

Может быть, переписать с целью вашего кода:

A a = null;
try {
  a = doSomethingThatWillThrowAnException();
} catch( ... ) {
  a = new A();
}
1 голос
/ 05 октября 2009

Только что провел тест на 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 голосов
/ 07 октября 2009

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

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

Ментальное примечание на следующий раз: «Сначала проверьте очевидное: если у вас странное поведение, код, который вы просматриваете, может не соответствовать тому, что было выполнено».

Еще раз спасибо, Cedric

0 голосов
/ 05 октября 2009

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

0 голосов
/ 05 октября 2009

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

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

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