java代码执行原理图 java程序运行代码( 二 )


1.Java指令集
Java虚拟机支持大约248个字节码 。每个字节码执行一种基本的CPU运算,例如,把一个整数加到寄存器,子程序转移等 。Java指令集相当于Java程序的汇编语言 。
Java指令集中的指令包含一个单字节的*作符,用于指定要执行的*作,还有0个或多个*作数,提供*作所需的参数或数据 。许多指令没有*作数,仅由一个单字节的*作符构成 。虚拟机的内层循环的执行过程如下:
do{
取一个*作符字节;
根据*作符的值执行一个动作;
}while(程序未结束)
由于指令系统的简单性,使得虚拟机执行的过程十分简单,从而有利于提高执行的效率 。指令中*作数的数量和大小是由*作符决定的 。如果*作数比一个字节大,那么它存储的顺序是高位字节优先 。例如,一个16位的参数存放时占用两个字节,其值为:
第一个字节*256+第二个字节字节码指令流一般只是字节对齐的 。指令tableswitch和lookup是例外,在这两条指令内部要求强制的4字节边界对齐 。
2.寄存器
Java虚拟机的寄存器用于保存机器的运行状态,与微处理器中的某些专用寄存器类似 。
Java虚拟机的寄存器有四种:
pc:Java程序计数器 。
optop:指向*作数栈顶端的指针 。
frame:指向当前执行方法的执行环境的指针 。
vars:指向当前执行方法的局部变量区第一个变量的指针 。
Java虚拟机
Java虚拟机是栈式的,它不定义或使用寄存器来传递或接受参数,其目的是为了保证指令集的简洁性和实现时的高效性(特别是对于寄存器数目不多的处理器) 。
所有寄存器都是32位的 。
3.栈
Java虚拟机的栈有三个区域:局部变量区、运行环境区、*作数区 。
(1)局部变量区 每个Java方法使用一个固定大小的局部变量集 。它们按照与vars寄存器的字偏移量来寻址 。局部变量都是32位的 。长整数和双精度浮点数占据了两个局部变量的空间,却按照第一个局部变量的索引来寻址 。(例如,一个具有索引n的局部变量,如果是一个双精度浮点数,那么它实际占据了索引n和n+1所代表的存储空间 。)虚拟机规范并不要求在局部变量中的64位的值是64位对齐的 。虚拟机提供了把局部变量中的值装载到*作数栈的指令, 也提供了把*作数栈中的值写入局部变量的指令 。
(2)运行环境区 在运行环境中包含的信息用于动态链接,正常的方法返回以及异常传播 。
·动态链接
运行环境包括对指向当前类和当前方法的解释器符号表的指针,用于支持方法代码的动态链接 。方法的class文件代码在引用要调用的方法和要访问的变量时使用符号 。动态链接把符号形式的方法调用翻译成实际方法调用,装载必要的类以解释还没有定义的符号,并把变量访问翻译成与这些变量运行时的存储结构相应的偏移地址 。动态链接方法和变量使得方法中使用的其它类的变化不会影响到本程序的代码 。
·正常的方法返回
如果当前方法正常地结束了,在执行了一条具有正确类型的返回指令时,调用的方法会得到一个返回值 。执行环境在正常返回的情况下用于恢复调用者的寄存器,并把调用者的程序计数器增加一个恰当的数值,以跳过已执行过的方法调用指令,然后在调用者的执行环境中继续执行下去 。
·异常和错误传播
异常情况在Java中被称作Error(错误)或Exception(异常),是Throwable类的子类,在程序中的原因是:①动态链接错,如无法找到所需的class文件 。②运行时错,如对一个空指针的引用
·程序使用了throw语句 。
当异常发生时,Java虚拟机采取如下措施:
·检查与当前方法相联系的catch子句表 。每个catch子句包含其有效指令范围,能够处理的异常类型,以及处理异常的代码块地址 。

推荐阅读