Java虚拟机用方法调用栈(Method Invocation Stack)来跟踪一系列的方法调用过程。该堆栈保存了每个调用方法的本地信息(比如方法的局部变量)。当一个新方法被调用时,Java虚拟机把描述该方法的栈结构置入栈顶,位于栈顶的方法为正在执行的方法。图9-1描述了方法调用栈的结构,图中方法的调用顺序为:main()方法调用methodB()方法,methodB()方法调用methodA()方法。
图9-1 Java虚拟机的方法调用栈
当方法methodB()调用方法methodA()时,如果方法中的代码块可能抛出异常,有如下两种处理办法。
(1)如果当前方法有能力自己解决异常,就在当前方法中通过try-catch语句捕获并处理异常,例如下面的代码。
(2)如果当前方法没能力自己解决异常,就在方法的声明处通过throws语句声明抛出异常,例如下面的代码。
当一个方法正常执行完毕,Java虚拟机会从调用栈中弹出该方法的栈结构,然后继续处理前一个方法。如果在执行方法的过程中抛出异常,Java虚拟机必须找到能捕获该异常的catch代码块。它首先察看当前方法是否存在这样的catch代码块,如果存在,就执行该catch代码块;否则,Java虚拟机会从调用栈中弹出该方法的栈结构,继续到前一个方法中查找合适的catch代码块。
例如,当方法methodA()抛出SpecialException异常时,如果在该方法中提供了捕获SpecialException的catch代码块,就执行这个异常处理代码块。如果方法methodA()未捕获该异常,而是采用第二种方式声明抛出SpecialException,那么Java虚拟机的处理流程将退回到上层调用方法methodB(),再察看方法methodB()中有没有捕获SpecialException。如果在方法methodB()中存在捕获该异常的catch代码块,就执行这个catch代码块,此时定义方法methodB()的代码如下。
(www.daowen.com)
由此可见,在回溯过程中,如果Java虚拟机在某个方法中找到了处理该异常的代码块,则该方法的栈结构将成为栈顶元素,程序流程将转到该方法的异常处理代码部分继续执行。
如果方法methodB()也没有捕获SpecialException,而是声明抛出该异常,那么Java虚拟机的处理流程将退回到main()方法,此时定义方法methodB()的代码如下。
当Java虚拟机追溯到调用栈的最底部的方法,如果仍然没有找到处理该异常的代码块,将调用异常对象的printStackTrace()方法,打印来自方法调用栈的异常信息,随后整个应用程序被终止。例如运行如下代码后会打印输出如下异常信息。
会打印输出如下异常信息。
在上述代码中,类SpecialException表示某一种异常,如下代码是它的源程序。
免责声明:以上内容源自网络,版权归原作者所有,如有侵犯您的原创版权请告知,我们将尽快删除相关内容。