由Sun的javac制作的奇怪异常表条目 [英] Strange exception table entry produced by Sun's javac
问题描述
鉴于此计划:
class Test {
public static void main(String[] args) {
try {
throw new NullPointerException();
} catch (NullPointerException npe) {
System.out.println("In catch");
} finally {
System.out.println("In finally");
}
}
}
Sun的 javac
(v 1.6.0_24)生成以下字节码:
Sun's javac
(v 1.6.0_24) produces the following bytecode:
public static void main(java.lang.String[]);
// Instantiate / throw NPE
0: new #2; // class NullPointerException
3: dup
4: invokespecial #3; // Method NullPointerException."<init>":()V
7: athrow
// Start of catch clause
8: astore_1
9: getstatic #4; // Field System.out
12: ldc #5; // "In catch"
14: invokevirtual #6; // Method PrintStream.println
17: getstatic #4; // Field System.out
// Inlined finally block
20: ldc #7; // String In finally
22: invokevirtual #6; // Method PrintStream.println
25: goto 39
// Finally block
// store "incomming" exception(?)
28: astore_2
29: getstatic #4; // Field System.out
32: ldc #7; // "In finally"
34: invokevirtual #6; // Method PrintStream.println
// rethrow "incomming" exception
37: aload_2
38: athrow
39: return
使用以下异常表:
Exception table:
from to target type
0 8 8 Class NullPointerException
0 17 28 any
28 29 28 any
我的问题是:为什么它包含异常表中的最后一个条目?!
据我所知,它基本上是如果 astore_2
抛出一个异常,捕获它,并重试相同的指令。
My question is: Why on earth does it include that last entry in the exception table?!
As I understand it, it basically says "if the astore_2
throws an exception, catch it, and retry the same instruction".
即使使用空的try / catch / finally子句,例如
Such entry is produced even with empty try / catch / finally clauses such as
try {} catch (NullPointerException npe) {} finally {}
一些观察结果
- Eclipse编译器不会产生任何此类异常表条目
- JVM规范没有记录
astore
指令。 - 我知道JVM为任何指令抛出
VirtualMachineError
是合法的。我猜这个特殊的条目可以防止任何这样的错误从该指令传播出来。
- Eclipse compiler does not produce any such exception table entry
- The JVM spec does not document any runtime exceptions for the
astore
instruction. - I know that it is legal for the JVM to throw
VirtualMachineError
for any instruction. I guess the peculiar entry prevents any such errors from propagating out from that instruction.
推荐答案
那里只有两种可能的解释:编译器包含一个错误或者由于不明原因而放置一种水印。
There are only two possible explanations: the compiler contains a bug or it's placing a kind of watermark for obscure reasons.
该条目肯定是假的,因为finally块抛出的任何异常本身必须将执行流程发送到外部异常处理程序或最后阻止,但永远不要再次运行相同的finally块。
That entry is certainly bogus because any exception thrown by a finally block itself must send execution flow to outer exception handler or finally block, but never "run again" the same finally block.
此外,一个很好的证据表明它是一个bug / watermark事实上Eclipse(以及其他Java编译器)没有生成这样的条目,即使Eclipse生成的类在Sun的JVM上运行良好。
Also, a good evidence that it's a bug/watermark, is the fact that Eclipse (and perhaps other Java compilers) are not generating such entry, and even so Eclipse-generated classes work fine on Sun's JVM.
这就是说,这篇文章很有趣,因为它似乎是有效的并且验证了类文件。如果我是JVM实现者,我会忽略该条目并填写Sun / Oracle的错误!
That said, this post is interesting because it seems that the class file is valid and verified. If I were a JVM implementor, I would ignore that entry and fill a bug for Sun/Oracle!
这篇关于由Sun的javac制作的奇怪异常表条目的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!