显式调用 throw 语句在字节码级别用 athrow 指令表示。
例如,下面的代码段:
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 语句时,我们并不总是实例化一个新的异常类型。因此,查看 new 指令的参数类型不是解决方案。
答案 0 :(得分:2)
这是不可能的,因为给定的指令可能会抛出多种类型的异常。
考虑代码
throw foo ? new ClassCastException() : new IOException();
在更复杂的情况下,您可能会抛出一些在运行时确定的类型,或者甚至是从在运行时构造的类创建的。
答案 1 :(得分:0)
这个问题太笼统了。所以,这是通用答案。
您需要识别使athrow
操作码消耗的值的指令或指令,然后将数据流传递到创建该值的位置。
答案 2 :(得分:0)
异常实例是否来自 new 指令或其他内容并不重要。所有说明都是打字的。所以它可能来自字段读取,方法调用或作为参数传递......在所有情况下它都具有声明的类型。唯一的区别是,对于 new 指令,您现在声明的类型将完全匹配运行时类型。在所有其他情况下,它可以是声明类型的子类。
但是你必须解释方法并模拟指令对局部变量和操作数堆栈的影响,以找出最顶层堆栈条目对 athrow 指令的类型。