Java编译器是否优化了不可访问的异常捕获分支?

时间:2019-02-07 12:28:37

标签: java exception try-catch throw throws

为什么是代码

void methodThrowsException() /*throws  Exception*/{
    try {
      // throw new Exception();
    } catch (Exception e) {
      throw e;
    }
}

编译好了吗? AFAIK编译器不会分析代码是否会引发异常。 显然throw e;在这里永远不会运行(由于注释了// throw new Exception();),但是为什么编译器知道这一点?

2 个答案:

答案 0 :(得分:3)

javac编译器实际上并没有做很多优化。但是简单死代码检测和优化仍然可行。

在您的示例中:编译器可以轻松地检测到 try 块为空。空的try块无法抛出,因此所有catch块代码本质上都是 dead

因此,编译器可以进入,并在此处简单地将整个try / catch全部丢弃。这样就没有什么可以引发异常的了。

其中,当我们使用javap时,正是在字节码中找到的

  void methodThrowsException();
    Code:
       0: return

是的,另一个答案是完全正确的:这仅适用于这种方式,因为您使用的是Exception,更具体的(已检查)子类将导致编译器错误。

答案 1 :(得分:3)

编译器将检测未抛出的特定已检查异常,例如

void methodThrowsException() {
    try {
    } catch (URISyntaxException e) {
        throw e;
    }
}

将导致编译器错误:

exception java.net.URISyntaxException is never thrown in body of corresponding try statement

,但它不会检查运行时异常或诸如ExceptionErrorThrowable之类的异常层次结构根类型。 JLS 11.2.3. Exception Checking中对此进行了解释。