第八章虚拟机字节码执行引擎
局部变量表
A、类变量有两次赋初始值的过程:
1、一次在准备阶段赋予系统初始值;
2、另一次是在初始化阶段,赋予程序员定义的初始值。
B、局部变量没有这样的富裕默认值的机制,局部变量必须赋值后才能使用。
操作数栈
8.2.3动态连接
指向运行时常量池中该栈帧所属方法的引用。
8.2.4方法返回地址
1、正常完成出口
2、异常完成出口
8.2.5附加信息
8.3方法调用
8.3.1解析
在java语言中,符合"编译期可知,运行期不可变"这个要求的方法主要有静态方法和私有方法。前者直接与类关联,后者在外部不可访问。
只要能被invokestatic和invokespecial指令调用的方法都可以在解析阶段确定为一的调用版本。符合这个条件的有静态方法、私有方法、实例构造器和父类方法四类,这类方法可以称为非虚方法。
8.3.2分派
Java具备面向对象的三个基本特征:继承、封装和多态,分派调用解释了多态特征在java中是如何实现的。
-
静态分派
package com.jvmstudy.chapter8; public class StaticDispath { static class Human { } static class Man extends Human { } static class Woman extends Human { } public void sayHello(Human guy) { System.out.println("Hello guy!"); } public void sayHello(Woman guy) { System.out.println("Hello Woman!"); } public static void main(String[] args) { Human man = new Human(); Human woman = new Woman(); StaticDispath p = new StaticDispath(); p.sayHello(man); p.sayHello(woman); } }
-
Human woman = new Woman();
上面的Human称为变量的静态类型,Woman称为其实际类型,javac根据参数的静态类型决定使用哪个版本.
public static void main(java.lang.String[]); flags: ACC_PUBLIC, ACC_STATIC Code: stack=2, locals=4, args_size=1 0: new #38 // class com/jvmstudy/chapter8/StaticDispath$Human 3: dup 4: invokespecial #40 // Method com/jvmstudy/chapter8/StaticDispath$Human."<init>":()V 7: astore_1 8: new #41 // class com/jvmstudy/chapter8/StaticDispath$Woman 11: dup 12: invokespecial #43 // Method com/jvmstudy/chapter8/StaticDispath$Woman."<init>":()V 15: astore_2 16: new #1 // class com/jvmstudy/chapter8/StaticDispath 19: dup 20: invokespecial #44 // Method "<init>":()V 23: astore_3 24: aload_3 25: aload_1 26: invokevirtual #45 // Method sayHello:(Lcom/jvmstudy/chapter8/StaticDispath$Human;)V 29: aload_3 30: aload_2 31: invokevirtual #45 // Method sayHello:(Lcom/jvmstudy/chapter8/StaticDispath$Human;)V 34: return
26行和31行为其字节码代码
-
动态分派
Invokevirtual指令的解析过程:
- 找到操作数栈顶的第一个元素所指向的实际类型,记作C。
- 如果在类C中找到与常量的描述符和简单名称都符合的方法,则进行访问权限校验,如果通过泽返回这个方法的直接引用,查找过程结束,不通过则返回非法访问错误
- 否则从下向上依次对C的各个父类进行第2步的搜索和验证
- 如何找不到合适的方法则抛出java.lang.AbstractMethodError。
- 单分派与多分派
-
虚拟机动态分派的实现机制
动态分派非常频繁,最常用的稳定优化手段
为类在方法区建立一个虚方法表Vtable
接口也会有Itable
8.4基于栈的字节码解释执行引擎
8.4.2基于栈的指令集与基于寄存器的指令集
基于栈的指令集:零地址指令,它依赖操作数栈进行操作.
基于寄存器的指令集架构:依赖寄存器进行工作,依赖于具体硬件.