1

对throw语句的显式调用在字节码级别用throw指令表示。

例如,下面的代码片段:

private static SQLException thrower() throws SQLException
{
    throw new SQLException();
}

被翻译成以下字节码:

   private static java.sql.SQLException thrower()   throws java.sql.SQLException;
   Signature: ()Ljava/sql/SQLException;
   Code:
   0:   new #29; //class java/sql/SQLException
   3:   dup
   4:   invokespecial   #31; //Method java/sql/SQLException."<init>":()V
   7:   athrow

我的问题是:仅通过分析字节码,我怎么知道抛出的异常类型?

Obs.:值得一提的是,我们在源代码中调用throw语句时,并不总是实例化一个新的异常类型。因此,查看指令的参数类型不是解决方案。

4

3 回答 3

2

这是不可能的,因为给定的指令可能会引发不止一种类型的异常。

考虑代码

throw foo ? new ClassCastException() : new IOException();

在更复杂的情况下,您可能会抛出一些在运行时确定的类型,甚至是从运行时构造的类中创建的。

于 2013-09-12T19:39:08.183 回答
0

异常实例是来自指令还是其他东西都没有关系。所有的指令都是打字的。所以它可能来自字段读取、方法调用或作为参数传递……在所有情况下,它都有一个声明的类型。唯一的区别是,对于指令,您现在声明的类型将与运行时类型完全匹配。在所有其他情况下,它可能是声明类型的子类。

但是您必须解释该方法并模拟指令对局部变量和操作数堆栈的影响,以找出最顶层的堆栈条目对athrow指令具有哪种类型。

于 2013-09-13T17:14:22.283 回答
0

这个问题太笼统了。所以,这是通用的答案。

您需要识别为athrow操作码消耗价值的指令或指令,然后将数据流向上移动到创建该值的点。

于 2013-09-12T17:15:10.587 回答