[b]Frames (帧)[/b]
[b]帧[/b]是用来存储数据和部分结果(Partial results)的,同时,也用与动态链接,方法的返回值并分发异常等。
当一个方法被调用时,就会创建一个新的帧(即方法和帧是紧密关联的)。当方法调用结束后(包括正常结束或异常退出,比如抛出一个未被捕捉的异常),帧会被销毁。帧是从JVM的栈里得到内存空间的。每一个帧都有它们自己的局域变量数组(Array of local variables),自己的操作数栈和一个指向当前方法所在类的常量池的指针。
局域变量数组和操作数栈的尺寸大小是在编译时就决定的,与该帧关联的方法的代码有关。
在一个指定的控制线程中,就只有正在被执行的方法(executing Method)的帧是活动状态的,所以该帧称为“当前帧”(Current Frame)。(当然,该方法就成为Current Method, 而该方法的类就称之为Current Class)。所有针对局部变量和操作数栈的操作都是针对当前帧的。
当一个方法调用其他方法或者该方法结束后,其帧就不再是当前帧了。当一个方法被调用后,一个新的帧就被创建了,而控制权也转移给了这个新的帧。当一个方法结束后,就将其返回结果(如果有)返回给了调用它的上一个帧。
需要注意的是,线程创建的帧是线程私有的,不能与另一个线程共享。
下面介绍Frames中的一些概念
[b]Local Variables[/b]
每个帧都含有一个变量数组,我们称之为“局部变量区”(Local variables)。其长度在编译时已经确定了。
一个单独的局部变量可以容纳一个boolean、byte、char、short、int、float、reference或者returnAddress的值;一对局部变量的空间可以容纳一个long或者double的值。
JVM利用局部变量区来向方法传递参数。在类的方法(class method)调用中,参数是连续传递的,并且从局部变量的索性位置0开始算起。而一个实例方法(instance method)调用,索引号为0的局部变量中存放的是指向调用该方法的实例对象的指针,而方法的参数是从1开始存放的。(其实,实例方法的调用中,调用者的指针也是以隐藏参数的形式传进方法的,所以其索引位置为0)
[b]Operand Stacks[/b]
每一个帧都含有一个后进先出(LIFO)的操作数栈,该栈的最大深度也是在编译期间就决定了。
当一个帧被创建的时候,它所包含的操作数栈还是空的。JVM中那些装载常量,装载局部变量或者域的值的操作会将获得的值放置到操作数栈中。其他的指令会从该操作数栈中获得操作数,并对它们进行操作,并将结果返回操作数栈。操作数栈用在向方法传递参数或从方法获得返回结果的准备工作中。
iadd命令表示将两个int值相加,它需要从获得操作数栈顶上的两个int值。这两个int值都会操作数栈中被pop出来,然后相加,然后它们的和被放回至操作数栈的顶端;
如图[img]http://dl.iteye.com/upload/picture/pic/102166/3916591b-5ad2-32ce-a3f5-b37819caf7b4.jpg[/img]
JVM的操作指令必须是用于被操作的操作数的类型,比如,两个int值的操作数就不能被针对long型的操作指令操作。
[b]Dynamic Linking (动态链接)[/b]
(这一段看的不是特别清楚,就把英文贴出来…)
Each frame contains a reference to the runtime constant pool for
the type of the current method to support dynamic linking of the method code. The
class file code for a method refers to methods to be invoked and variables to be
accessed via symbolic references.
每一个帧都包含一个指向当前方法所在类的运行时常量池(Runtime Constant Pool)的指针,该指针就是用来支持该方法代码的动态链接(Dynamic Linking)的。class文件的方法代码中包含了通过符号引用(Symbolic references) 来表示将要被调用的方法和将要被访问的常量。
Dynamic linking translates these symbolic
method references into concrete method references, loading classes as necessary
to resolve as-yet-undefined symbols, and translates variable accesses into appropriate
offsets in storage structures associated with the runtime location of these
variables.
动态链接就是将这些符号引用转变为固定的方法引用,并加载必须的类来解析那些尚未被定义的符号,并根据变量在运行时的位置将这些变量引用转变为存储解释中恰当的偏移量。(即将编译时不确定的在运行时变为确定的)
This late binding of the methods and variables makes changes in other classes
that a method uses less likely to break this code.
[b]Normal Method Invocation Completion (正常的方法调用完成)[/b]
如果一个方法调用没有产生被抛出的异常(或者直接从JVM被抛出,或者从一个被显示声明的throw抛出),那么这个方法就是正常就完成调用。当一个方法正常完成后,一般会给该方法的调用者返回一个值。当前帧被用于存储调用者的状态,包括它的本地变量区和操作数栈,以及指向方法调用指令的program counter。在返回值(如果有)被push回调用者帧的操作数栈后,程序会继续在调用者的帧中继续运行。
[b]Abrupt Method Invocation Completion (方法的异常退出)[/b]
同正常的相反,突发的就是指JVM运行某指令时抛出了某个异常,并且这个异常没有在方法中被处理掉后,方法就称之为异常退出(Complete Abruptly),一个athrow指令也会造成一个异常被显式的被抛出,当然,这是在该异常没有在方法内部被解决掉的情况。一个方法的异常退出不会给其调用者返回结果。
[b]帧[/b]是用来存储数据和部分结果(Partial results)的,同时,也用与动态链接,方法的返回值并分发异常等。
当一个方法被调用时,就会创建一个新的帧(即方法和帧是紧密关联的)。当方法调用结束后(包括正常结束或异常退出,比如抛出一个未被捕捉的异常),帧会被销毁。帧是从JVM的栈里得到内存空间的。每一个帧都有它们自己的局域变量数组(Array of local variables),自己的操作数栈和一个指向当前方法所在类的常量池的指针。
局域变量数组和操作数栈的尺寸大小是在编译时就决定的,与该帧关联的方法的代码有关。
在一个指定的控制线程中,就只有正在被执行的方法(executing Method)的帧是活动状态的,所以该帧称为“当前帧”(Current Frame)。(当然,该方法就成为Current Method, 而该方法的类就称之为Current Class)。所有针对局部变量和操作数栈的操作都是针对当前帧的。
当一个方法调用其他方法或者该方法结束后,其帧就不再是当前帧了。当一个方法被调用后,一个新的帧就被创建了,而控制权也转移给了这个新的帧。当一个方法结束后,就将其返回结果(如果有)返回给了调用它的上一个帧。
需要注意的是,线程创建的帧是线程私有的,不能与另一个线程共享。
下面介绍Frames中的一些概念
[b]Local Variables[/b]
每个帧都含有一个变量数组,我们称之为“局部变量区”(Local variables)。其长度在编译时已经确定了。
一个单独的局部变量可以容纳一个boolean、byte、char、short、int、float、reference或者returnAddress的值;一对局部变量的空间可以容纳一个long或者double的值。
JVM利用局部变量区来向方法传递参数。在类的方法(class method)调用中,参数是连续传递的,并且从局部变量的索性位置0开始算起。而一个实例方法(instance method)调用,索引号为0的局部变量中存放的是指向调用该方法的实例对象的指针,而方法的参数是从1开始存放的。(其实,实例方法的调用中,调用者的指针也是以隐藏参数的形式传进方法的,所以其索引位置为0)
[b]Operand Stacks[/b]
每一个帧都含有一个后进先出(LIFO)的操作数栈,该栈的最大深度也是在编译期间就决定了。
当一个帧被创建的时候,它所包含的操作数栈还是空的。JVM中那些装载常量,装载局部变量或者域的值的操作会将获得的值放置到操作数栈中。其他的指令会从该操作数栈中获得操作数,并对它们进行操作,并将结果返回操作数栈。操作数栈用在向方法传递参数或从方法获得返回结果的准备工作中。
iadd命令表示将两个int值相加,它需要从获得操作数栈顶上的两个int值。这两个int值都会操作数栈中被pop出来,然后相加,然后它们的和被放回至操作数栈的顶端;
如图[img]http://dl.iteye.com/upload/picture/pic/102166/3916591b-5ad2-32ce-a3f5-b37819caf7b4.jpg[/img]
JVM的操作指令必须是用于被操作的操作数的类型,比如,两个int值的操作数就不能被针对long型的操作指令操作。
[b]Dynamic Linking (动态链接)[/b]
(这一段看的不是特别清楚,就把英文贴出来…)
Each frame contains a reference to the runtime constant pool for
the type of the current method to support dynamic linking of the method code. The
class file code for a method refers to methods to be invoked and variables to be
accessed via symbolic references.
每一个帧都包含一个指向当前方法所在类的运行时常量池(Runtime Constant Pool)的指针,该指针就是用来支持该方法代码的动态链接(Dynamic Linking)的。class文件的方法代码中包含了通过符号引用(Symbolic references) 来表示将要被调用的方法和将要被访问的常量。
Dynamic linking translates these symbolic
method references into concrete method references, loading classes as necessary
to resolve as-yet-undefined symbols, and translates variable accesses into appropriate
offsets in storage structures associated with the runtime location of these
variables.
动态链接就是将这些符号引用转变为固定的方法引用,并加载必须的类来解析那些尚未被定义的符号,并根据变量在运行时的位置将这些变量引用转变为存储解释中恰当的偏移量。(即将编译时不确定的在运行时变为确定的)
This late binding of the methods and variables makes changes in other classes
that a method uses less likely to break this code.
[b]Normal Method Invocation Completion (正常的方法调用完成)[/b]
如果一个方法调用没有产生被抛出的异常(或者直接从JVM被抛出,或者从一个被显示声明的throw抛出),那么这个方法就是正常就完成调用。当一个方法正常完成后,一般会给该方法的调用者返回一个值。当前帧被用于存储调用者的状态,包括它的本地变量区和操作数栈,以及指向方法调用指令的program counter。在返回值(如果有)被push回调用者帧的操作数栈后,程序会继续在调用者的帧中继续运行。
[b]Abrupt Method Invocation Completion (方法的异常退出)[/b]
同正常的相反,突发的就是指JVM运行某指令时抛出了某个异常,并且这个异常没有在方法中被处理掉后,方法就称之为异常退出(Complete Abruptly),一个athrow指令也会造成一个异常被显式的被抛出,当然,这是在该异常没有在方法内部被解决掉的情况。一个方法的异常退出不会给其调用者返回结果。