从我的理解, throw
是一颗灵长类动物的JVM命令。 当这个被调用时,JVM“检查当前调用堆栈可以抓住它。” 如果不能,那么Java简单地弹出调用栈几乎完全一样,如果返回被调用。 那么JVM“检查当前调用堆栈可以抓住它”等等递归。
我的问题:它怎么可能算法为JVM知道在哪里调用栈可以赶上一个给定的例外? 有没有的元数据存储在每个调用堆栈入口映射例外代码块? 有没有在某种程度上会自动跟踪堆的静态数据结构? 因为地方必须有数据保持跟踪。
从我的理解, throw
是一颗灵长类动物的JVM命令。 当这个被调用时,JVM“检查当前调用堆栈可以抓住它。” 如果不能,那么Java简单地弹出调用栈几乎完全一样,如果返回被调用。 那么JVM“检查当前调用堆栈可以抓住它”等等递归。
我的问题:它怎么可能算法为JVM知道在哪里调用栈可以赶上一个给定的例外? 有没有的元数据存储在每个调用堆栈入口映射例外代码块? 有没有在某种程度上会自动跟踪堆的静态数据结构? 因为地方必须有数据保持跟踪。
在JVM规范有这个细节。
特别是, 第4.7.3节提供了有关异常表,这是一系列的条目说这异常哪些指令夹缝中的细节。 第3.12节给出了一个具体的例子。
这个元数据如何映射到本地代码的JIT当然是另当别论, - 和具体实现的。 例如,可能会有一些映射从本地实时编译代码回到原来的位置,字节码指令的每个位置,此时的异常表可以协商,以找到合适的处理程序回来。
一般来说:当一个异常被抛出的JVM提取“调用栈”。 这标识该字节码或机器指令正在在调用堆栈每个水平执行时,与该位置关联的类和方法一起。
然后,堆栈中的每个方法(从其中异常发生和向后工作方法),JVM长相(在内部类对象)在方法的表映射的try / catch范围成字节码/机器指令范围。
如果一个“匹配”在表中找到一种方法,和被抛出异常的类型正被监视的一类用于在找到的范围内,则控制被转移到catch
入口点,异常设置成一种后参数的位置,这样的catch
子句可以参考它。
如果表中,然后调用堆栈有效地在try / catch语句的前面方法的表“弹出”,放置在堆栈的顶部的下一个较早的方法,和上面搜索“匹配”未找到“匹配”范围是重复的。
当然这是一个过于简单化。 有很多参与处理额外的逻辑的finally
范围,例如,一些“边缘”的情况。