您的位置:首页 > 其它

JVM之虚拟机字节码执行引擎

2017-12-05 16:54 190 查看
运行时栈帧结构:

栈帧存储方法的局部变量表、操作数栈、动态链接和方法返回地址等,每一个方法由开始到结束,都对应着一个栈帧在虚拟机里面的出栈入栈过程。

对于执行引擎来说,在活动的线程中,只有位于栈顶的栈帧才有效,叫做当前栈帧,与这个栈帧相关联的方法叫做当前方法。

局部变量表:

是一组变量值存储空间,存放方法参数和方法内部的局部变量。以变量槽为最小单位,在方法执行的时候,虚拟机使用局部变量表完成参数值到参数变量列表的传递过程,如果执行的是实例方法,局部变量表中的第0位索引的Slot默认用于传递方法所属对象实例的引用,在方法中可以用this来访问这个隐藏的参数。这也就说明了,为什么静态方法不能直接访问非静态变量和调用非静态方法。

局部变量表不会像类变量存在准备阶段,类变量有两次初始化过程,一是准备阶段,赋予系统默认值,二是初始化阶段,赋予程序定义的值。而局部变量表必须进行初始化,只定义没有赋值是无法使用的。

操作数栈:

后入先出的栈,编译时确定最大深度,在方法执行是会往操作数栈中写入或者提取内容。操作数栈中的数据类型必须与字节码指令的序列严格匹配。

动态链接:

每个栈帧都包含一个指向运行时常量池中该栈帧所属方法的引用,只持有这个引用是为了支持方法调用过程中的动态链接。

方法返回地址:

当一个方法执行时只有两种方法退出,第一种是执行引擎遇到任意一个方法返回的字节码指令,这时候可能会返回值传递给上层的方法调用者,称为正常退出。第二种是在执行过程中遇到了异常,并且这个异常没有在方法体内处理,称为异常完成出口,是不会给上层调用者返回任何东西的。

方法调用:

方法调用不等于方法执行,方法调用阶段唯一的作用是确定方法的版本

所有方法调用中的目标方法在Class文件中都是一个常量池中的符号引用,在类加载解析阶段,会将其中一部分转换为直接引用,即方法的入口地址。这种接戏的前提是方法在真正运行前可以被唯一的确定一个版本,并且这个方法版本在运行期是不可改变的,主要包括静态方法、私有方法、实例构造器、父类方法,这类方法的调用过程称为解析。这类方法叫做非虚方法,其他方法叫做虚方法,除了final方法,因为final方法不可以被覆盖,所以也是非虚方法。

分派:

静态分派:变量有静态类型和实例类型,Super a = new Sub();Super是a的静态类型,Sub是a的实例类型,区别静态类型只有在使用时发生,变量本身的静态类型不会发生变化,并且最终的静态类型是编译可知的。实例类型变化的结果在编译器才可以确定。虚拟机在重载的时候通过使用静态类型而不是实例类型作为判断依据的。静态分派的典型应用就是方法重载,发生在编译阶段。

动态分派:方法的重写,执行过程是invokevirtual:先找到操作数栈顶的第一个元素所指向的实例类型,判断与常量池中的描述符是否完全一致,否则对父类进行搜索。

单分派与多分派:方法的接受着与方法的参数统称为方法的宗量,静态分派时首先需要判断静态类型,还需要参数,所以是多分派。动态分派因为只关心实例类型,并且方法签名完全一致,包含了参数,所以是单分派。

未完待续.......
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: