2

下面是一些示例代码来说明我们的问题:

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

问题是finally块中打印的'a'的值是什么......

我不确定,我想我偶然发现了一些可能无法完全描述的东西。我在笔记本电脑(x86 上的 jdk1.6.0.16)上观察到“a”等于 A()。但是,对于 Solaris 上的 JDK 1.4,我认为该值为 null(就像即使抛出异常也执行了赋值一样)。这显然与错误有关,我们将部署一个没有分配的版本只是为了确保但我们想知道你们中的一个人是否也注意到了这一点或有某种解释要提出。

我们还将做一个示例程序来在有问题的 JDK 上演示这一点……我们将发布结果。

4

6 回答 6

5

发生异常时绝对不应该发生分配 - 这将是 JVM 中的一个非常严重的错误。但我首先怀疑异常实际上发生在其他地方(例如在构造函数 A() 中)。

于 2009-10-05T13:54:11.637 回答
2

我会假设a == new A()除非它被优化掉。代码看起来是不是有点傻:

a=1;
a=2;

也许重写你的代码的意图:

A a = null;
try {
  a = doSomethingThatWillThrowAnException();
} catch( ... ) {
  a = new A();
}
于 2009-10-05T14:04:29.797 回答
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()构造函数中引发了异常。(我希望是这样,否则需要一些非常讨厌的防御代码)

于 2009-10-05T14:37:39.957 回答
0

我也使用 JDK 1.4.2 在 Solaris 10 上运行了代码,它的行为正确。问题是生产中的代码不是我正在查看的代码......(以前的版本)

阅读您的答案很有趣,因为它清楚地表明优化器故障可能会发生,并且再次猜测引擎盖下发生的事情总是一个好主意。

下一次的心理注释:“首先,检查显而易见的:如果你有一个奇怪的行为,你看到的代码可能不是已经执行的代码。”

再次感谢,塞德里克

于 2009-10-07T10:16:09.863 回答
0

如果优化器可以确保new A()没有副作用,它将优化第一个分配。要隔离这种情况,请禁用 JIT 并再次运行代码。如果a != null之后,您会看到优化器故障。

明显的解决方法是new A()在块之前进行更多操作try

A a = new A();
try {
  a = doSomethingThatWillThrowAnException();
} finally {
  System.out.println("A = " + a);
}
于 2009-10-05T13:54:07.253 回答
0

您可以尝试编译代码,然后查看字节码以了解发生了什么。我使用来自http://andrei.gmxhome.de/eclipse/的字节码大纲 eclipse 插件

于 2009-10-05T14:21:33.457 回答