字节码执行引擎


JVM 字节码执行引擎

JVM 作为字节码与操作系统之间的中间件,实现了 java 的跨平台性。

JVM 输入的是字节码文件,执行引擎(Execution Engine) 的任务就是将字节码指令解释/编译为对应平台上的本地机器指令才可以。简单来说,JVM 中的执行引擎充当了将高级语言翻译为机器语言的译者。

1. JVM 运行时数据结构

详情看 [JVM 内存结构总结]。

2. 方法调用

方法调用是指确定方法的版本,不涉及方法内部的执行过程。

一切方法调用在 .class 文件里存储的都只是符号引用,这是需要在类加载期间或者是运行期间,才能确定为方法在实际 运行时内存布局中的入口地址(相当于类加载中解析阶段中把符号引用替换为直接引用)。

2.1 类加载中对方法调用的解析

类加载的解析,是对 class 文件中的符号引用转化为 JVM 内存结构中的直接引用。

JVM 中方法调用字节码的指令:

  • invokestatic: 调用静态方法
  • invokespecial: 调用实例构造器方法、私有方法、父类方法
  • invokevirtual: 调用所有的虚方法:可以被重写的方法
  • invokeinterface:调用接口方法
  • invokedynamic: 用来实现动态语言特性。先在运行时动态解析出点限定符锁引用的方法,然后执行该方法。

2.2 方法的分派调用

分派是多态的体现。体现在方法的重载重写上。

List<Integer> list = new ArrayList();

List静态类型ArrayList实际类型

  • 静态类型在编译期确定
  • 实际类型在运行时才确定

2.2.1 静态分派

静态分派是指依赖静态类型来绑定方法的直接引用,的分派行为,在编译阶段完成。

  • 静态分派应用于方法的重载调用。

区分被重载的函数取决于方法签名。

  • 方法名
  • 参数类型
  • 参数个数

被重载函数的调用时,方法参数类型取决于静态类型,即编译器即确定了方法参数类型。

2.2.2 动态分派

动态分派是指,在运行时,根据实际类型确定方法版本的分派过程。

  • 应用是方法的重写

若类 A 的实际类型是子类,则调用类 A 的重写方法,是通过动态分派来确定的。

动态分派的实现

动态方法是利用了 JVM 方法区中的 虚方法表 Virtual Method Table, 存放各个虚方法的实际入口地址。

  • 若子类方法没有重写父类方法,则指向父类的实现。
  • 若子类方法重写了父类方法,则指向子类方法。

虚方法表一般在类加载的连接阶段进行初始化。

qianzhaokun-Java方法的调用过程

3. 代码编译与字节码执行过程

静态代码编译

Java 的编译期有两个阶段:

  1. 静态编译阶段:前端编译器把 java 文件编译成 .class 字节码文件;
  2. 动态编译阶段:JIT 编译器把字节码编译成机器码;

其中第二阶段不是必须的,它是JVM对热点代码作出的一些优化。

字节码解释器 interpreter

解释器采用逐行解释的操作,当一条字节码指令被解释执行完成后,接着在根据 PC 寄存器中记录的下一条需要被执行的字节码指令执行解释操作。

JIT, just in time compiler 即时编译器

JVM 将字节码直接编译成和本地机器平台相关的机器语言。主流 JVM 如 HotSpot 虚拟机采用解释器与JIT并存的结构。

早期的虚拟机是只采用解释器 interpreter 对字节码进行逐行解释执行,当虚拟机发现了热点代码时,会采用 JIT 编译的方式把字节码直接编译成机器码,加快执行速度。

  • 时间开销:速度加快指的是编译后的执行速度加快,但编译需要一定的时间
  • 空间开销:字节码编译成机器码后,内存膨胀10x。所以只对热点代码进行编译,否则会造成代码爆炸
如何发现热点代码

两种方式:

  1. 周期性的对线程栈进行采样,出现频次高的。
    • 缺点:线程由于阻塞或其他原因可能导致长期位于线程栈中,导致结果不准确
  2. 为方法/代码块建立计数器,次数达到阈值。

hot spot 虚拟机采用的是计数器法

字节码的执行

字节码主要是为了实现特定软件运行和软件环境、与硬件环境无关。


文章作者: Yu Yang
版权声明: 本博客所有文章除特別声明外,均采用 CC BY 4.0 许可协议。转载请注明来源 Yu Yang !
 上一篇
JVM 基础 JVM 基础
JVM 基础1. Java 程序的执行流程 java 程序首先经过编译器 javac 的编译,然后交给虚拟机 java。 字节码的运行过程: 通过类装载子系统来加载数据到运行时数据区 通过字节码执行引擎来执行代码
2020-09-26
下一篇 
于氏麻辣小龙虾 于氏麻辣小龙虾
于氏麻辣小龙虾 浸泡吐脏东西:泡小龙虾的水加盐,泡2小时。 清洗:戴手套,用刷子清洗小龙虾,并去虾线。 再次浸泡去血水:水里加盐去血水。 炒制:锅里热油两勺,加大葱段、姜片、大蒜、小葱结、干花椒,加火锅底料一小块,炒制出香。然后下入小龙虾,
2020-05-05
  目录