当前位置: 首页 > 面试题库 >

Sun的javac产生的奇怪异常表条目

葛言
2023-03-14
问题内容

鉴于此程序:

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)产生以下字节码:

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引发异常,请捕获它,然后重试相同的指令 ”。

即使使用空try / catch / finally子句(例如

try {} catch (NullPointerException npe) {} finally {}

一些观察

  • Eclipse编译器不会产生任何此类异常表条目
  • JVM规范没有记录该astore指令的任何运行时异常。
  • 我知道JVM抛出VirtualMachineError任何指令都是合法的。我想特殊的输入可以防止任何此类错误从该指令中传播出来。

问题答案:

仅有两种可能的解释:编译器包含一个错误,或者出于晦涩的原因,它正在放置一种水印。

该条目肯定是虚假的,因为由finally块本身抛出的任何异常都必须将执行流发送到外部异常处理程序或finally块,但切勿“再次运行”相同的finally块。

同样,一个很好的证据证明它是一个错误/水印,事实是Eclipse(也许还有其他Java编译器)没有生成这样的条目,甚至Eclipse生成的类在Sun的JVM上都能正常工作。

就是说,这篇文章很有趣,因为看来该类文件是有效且经过验证的。如果我是JVM实现者,那么我将忽略该条目并填充Sun / Oracle的错误!



 类似资料:
  • 问题内容: 基本上,该网站可以正常运行12多个小时,然后突然停止工作。我将开始在以前运行良好的LINQ查询中引发奇怪的异常。 我在这篇文章的底部提供了堆栈跟踪。 根据在类似SO帖子上找到的建议,我通过直接从Server Explorer中的DB拖动表来删除并重新制作了DBML。比较Git中的新旧内容,我发现了一些不同的字段: 在dbml中将varchar(255)的一个实例设置为nchar(10)

  • 问题内容: 有人可以解释一下为什么在第一种情况下检测到空指针,而在另一种情况下却没有吗? 也许他总是看第一种类型,但是为什么他只在条件为假的情况下才这样做。 问题答案: 当您使用三元运算符时, 转换时,类型1和类型2必须具有相同的类型。首先,它实现了type1,然后实现了type2。 现在看看你的情况 因为is 并且它将作为原始,并且因为正试图将其转换为。因此为空指针。 在哪里一样棘手的测试5 由

  • 问题内容: 我在做什么 : 我预期的输出: 平均=(10 + 20 + 30)/ 5 = 12 MYSQL的输出: 平均值=(10 + 20 + 30)/ 3 = 20 理想情况下,我想要的是MYSQL应该得到5行的总和并除以5,但是它只能除以3(非NULL行) 为什么会发生这种情况,我该怎么做才能获得正确的AVG,即60/5?PS:我不能使标记字段NOT NULL,在我的数据库设计中,标记字段允

  • 我有一个基于Spring的webapp,我的问题是在代码更改后,我开始出现延迟加载异常。下面我详细描述了这种情况: 在开始的时候 我有一个账户和文字实体。一个帐户可以有多个单词,一个单词可以分配给多个帐户。 一个ccount.class 单词班 除了每个账户只能有一个“WordForToday”,它由账户中映射的单词实体表示。类如下: 一切都正常工作。特别是我有一个@Schedilly方法,每天调

  • 下面是我的节点类 下面是我的带有插入方法的链表类 我得到以下结果, 端部插入20 正在打印节点1-->10-->5-->none->NULL

  • 我创建了两个长列表,重复两个不同的值。在第一个列表中,值交替出现,在第二个列表中,一个值出现在另一个值之前: 然后我迭代它们,对它们不做任何操作: 两者哪个迭代更快?取决于我如何测量!我用每种计时方法跑了50场比赛: 为什么这两种计时方法给我的结果完全相反?为什么这两个列表之间存在速度差异?我希望有两次25-25,而不是50-0和0-50。 之前类似问题的原因以及我认为他们不应该对此负责的原因: