Java Virtual Machine的结构 4

1 Run-Time Data Areas

2 Frames

2.1 Local Variables

每个frame框包含一个被称之为本地变量的数组,数组的长度在编译期确定而以二进制的表现方式跟随类或者接口的与frame框对应的方法代码。一个本地变量赋予的值类型包括boolean、byte、char、short、int、float、reference、returnAddress,一对本地变量赋予的值类型包括long、double(64位)。

本地变量使用索引的方式寻址,第一个本地变量的索引值是0,假设本地变量数组的长度是n,则其索引的合法范围是0到n-1。一个long或者double值占用两个连续的本地变量空间,假设该本地变量的存在数组的n索引中,则实际上其占用的位置n与n+1,因此,不能单独加载n索引位或者n+1索引位的值,需要作为一个整体同时加载n与n+1索引位。

JVM在方法调用的过程中使用本地变量传递参数,方法参数的传递的索引位是连续的,从索引位0开始,在Java实例方法的调用过程中,索引位0是实例本身(Java语言中对应this),其他参数是从索引位1开始的。

2.2 Operand Stacks

每个frame框包含一个后进先出的栈,被称之为操作数栈,该栈的最大深度是在编译期确定而跟随类或者接口的与frame框对应的方法代码,一般情况下,根据方法调用的上下文关系,将当前frame框的操作数作为操作数栈,该操作数栈创建的时候是空的,JVM提供指令将常量、值或者作用域从本地变量中加载入操作数栈中,JVM指令将从操作数栈取出操作数,对操作数执行指令计算得出结果,将计算结果压入操作数栈中作为下一个JVM指令的操作数,操作数栈也可为方法准备参数、接受方法返回的结果。

例如,JVM指令iadd是两个int类型的相加,其操作数对应两个int类型的值,JVM先将两个int类型的值压入操作数栈中,使用指令iadd将操作数栈的两个int类型的值出栈,执行相加的计算而得出结果,JVM将计算所得的结果值压入操作数栈中,作为下一个JVM指令的操作数。在操作数栈中的类型必须符合JVM指令规定的操作数类型,例如,int类型的操作数不能作为long或者double类型参数计算,在操作数栈深度的计算中,一个long或者double类型的操作数是作为两个单元的深度计算,而其他操作数是作为一个单元的深度计算。

2.3 Dynamic Linking

每个frame框包含一个对运行时常量池的引用,其引用的是当前方法的类型以支持方法代码的动态链接,一个方法的class类文件代码是指被调用的方法以及使用符号引用而涉及到的变量,动态链接将这些符号方法的引用翻译成具体方法引用、加载需要依赖的类、将变量的访问翻译成内存存储结构中适当的偏移地址(变量在运行时的地址)。

2.4 Normal Method Invocation Completion

一个方法的调用正常地完成而没有发生JVM类型的异常或者代码抛出的异常,如果方法能正常地被执行,则该方法能正确地返回方法的返回类型的值,当前frame框包含以及存储了调用者相关的变量以及操作数栈,JVM将方法调用完成的返回值保持在操作数栈中。

2.5 Abrupt Method Invocation Completion

一个方法调用的过程中发生JVM类型的异常或者代码抛出的异常,如果代码中异常没有捕获,则调用者永远得不到方法返回的结果,该方法的调用过程是异常调用完成。

(未完待续)

猜你喜欢

转载自blog.csdn.net/uesowys/article/details/129648835