java 编译器是否优化了无法访问的异常捕获分支?
Does java compiler optimize unreachable exception catch branches?
为什么是代码
void methodThrowsException() /*throws Exception*/{
try {
// throw new Exception();
} catch (Exception e) {
throw e;
}
}
编得好吗?
AFAIK 编译器不会分析代码是否会抛出异常。
这里很明显 throw e;
永远不会 运行(由于注释 // throw new Exception();
),但为什么编译器知道这一点?
javac 编译器确实没有做很多优化。但是 简单 死代码检测和优化仍然是可能的。
在您的示例中:编译器可以轻松检测到 try 块为空。空的 try 块不能抛出,所以所有的 catch 块代码本质上是 dead。
所以编译器 可以 进入并简单地将整个 try/catch 一起放到这里。然后就没有什么可以抛出异常了。
其中,当我们使用 javap 时,正是我们在字节码中发现的:
void methodThrowsException();
Code:
0: return
是的,另一个答案是完全正确的:这只能以这种方式工作,因为您使用的是 Exception
,更具体(已检查)的子类将导致编译器错误。
编译器将检测未抛出的特定检查异常,例如
void methodThrowsException() {
try {
} catch (URISyntaxException e) {
throw e;
}
}
会导致编译错误:
exception java.net.URISyntaxException is never thrown in body of corresponding try statement
但它不会检查运行时异常,或像 Exception
、Error
、Throwable
这样的异常层次根类型。 JLS 11.2.3. Exception Checking.
中对此进行了解释
为什么是代码
void methodThrowsException() /*throws Exception*/{
try {
// throw new Exception();
} catch (Exception e) {
throw e;
}
}
编得好吗?
AFAIK 编译器不会分析代码是否会抛出异常。
这里很明显 throw e;
永远不会 运行(由于注释 // throw new Exception();
),但为什么编译器知道这一点?
javac 编译器确实没有做很多优化。但是 简单 死代码检测和优化仍然是可能的。
在您的示例中:编译器可以轻松检测到 try 块为空。空的 try 块不能抛出,所以所有的 catch 块代码本质上是 dead。
所以编译器 可以 进入并简单地将整个 try/catch 一起放到这里。然后就没有什么可以抛出异常了。
其中,当我们使用 javap 时,正是我们在字节码中发现的:
void methodThrowsException();
Code:
0: return
是的,另一个答案是完全正确的:这只能以这种方式工作,因为您使用的是 Exception
,更具体(已检查)的子类将导致编译器错误。
编译器将检测未抛出的特定检查异常,例如
void methodThrowsException() {
try {
} catch (URISyntaxException e) {
throw e;
}
}
会导致编译错误:
exception java.net.URISyntaxException is never thrown in body of corresponding try statement
但它不会检查运行时异常,或像 Exception
、Error
、Throwable
这样的异常层次根类型。 JLS 11.2.3. Exception Checking.