《Java 虚拟机原理》1.1 什么是Java虚拟机
时间:2023-07-15 01:12:01 | 来源:网站运营
时间:2023-07-15 01:12:01 来源:网站运营
《Java 虚拟机原理》1.1 什么是Java虚拟机:
一、Java虚拟机Java 虚拟机(JVM)是运行 Java 字节码的虚拟机。JVM 有针对不同系统的特定实现(Windows,Linux,macOS),目的是使用相同的字节码,它们都会给出相同的结果。字节码和不同系统的 JVM 实现是 Java 语言“
一次编译到处运行”的关键。
什么是字节码?采用字节码的好处是什么?字节码(即扩展名为 .class 的文件) 是JVM 可以理解的代码,它不面向任何特定的处理器,只面向虚拟机。Java 语言通过字节码的方式,在一定程度上解决了传统解释型语言执行效率低的问题,同时又保留了解释型语言可移植的特点。因此,Java 程序无须重新编译便可在多种不同操作系统的计算机上运行。
Java 程序从源代码到运行一般有下面 3 步:java运行流程
字节码=》机器码 :在这一步 JVM 类加载器首先加载字节码文件,然后通过解释器逐行解释执行,这种方式的执行速度会相对比较慢。同时,有些方法和代码块是经常需要被调用的(也就是所谓的热点代码),所以后面引进了
JIT 编译器,而 JIT 属于运行时编译。
当 JIT 编译器完成第一次编译后,其会将字节码对应的机器码保存下来,下次可以直接使用。而我们知道,机器码的运行效率肯定是高于 Java 解释器的。这也解释了我们为什么经常会说 Java 是编译与解释共存的语言。
二、Java编译运行的总流程java语言是可以在各种操作系统中运行,即“
一次编译,到处运行”(Write once, run anywhere)。还有另外一个特点:垃圾收集,即自动分配和回收内存。
如何实现“
一次编译,到处运行”?
总体流程:1.java源代码被javac编译器编译成class二进制字节码文件;2.class被jvm加载到内存中;3.字节码执行引擎将class转换为可以直接运行的机器码。
图1 总体流程
1.字节码生成通过上面的简述我们已经知道,java语言中是用过javac程序将java文件编译成class文件的,编译的过程大约分为如下四步:
(1)词法分析器:将代码(字符流)中关键字和标识符等内容解析转换成Token流,token流就是一组对应源码字符集和的单词序列;
(2)语法分析器:解析Token流中package关键字声明、import关键字声明和class主体信息,组建成更加结构话的语法树;
(3)语义分析器:对语法树进一步处理,包括添加默认构造函数、检查变量初始化、常量合并处理、检查操作变量类型是否匹配、检查操作语句是否可达、异常是否捕获或抛出、接触java语法糖等;
(4)代码生成器:调用com.sun.tools.javac.jvm.Gen类遍历语法树,生成最终字节码;
如下图2所示:
图2 字节码的生成流程图
2.类加载过程Class 文件需要加载到虚拟机中之后才能运行和使用,那么虚拟机是如何加载这些 Class 文件呢?
系统加载 Class 类型的文件主要三步:
加载->连接->初始化。连接过程又可分为三步:
验证->准备->解析。如下图3所示:
图3 类加载流程图
3.字节码引擎字节码引擎:
基于栈的字节码解释执行引擎,其流程是抽象语法树 -> 指令流(可选)-> 解析器 -> 解析执行。
程序代码到物理机的目标代码或者虚拟机执行的指令之前,都需要经过下图中的各个步骤。下图4中最下面的那条分支,就是传统编译原理中程序代码到目标机器代码的生成过程;中间那条分支,则是解释执行的过程。
图4 现代编译流程
基于物理机、Java 虚拟机或者非 Java 的其它高级语言虚拟机的语言,大多都会遵循这种基于现代编译原理的思路,在执行前先对程序源代码进行词法分析和语法分析处理,把源代码转化为抽象语法树。对于一门具体语言的实现来说,词法分析、语法分析以至后面的优化器和目标代码生成器都可以选择独立于执行引擎,形成一个完整意义的编译器去实现,这类代表是 C/C++。也可以为一个半独立的编译器,这类代表是 Java。又或者把这些步骤和执行全部封装在一个封闭的黑匣子中,如大多数的 JavaScript 执行器。
Java 语言的编译与解析是分开的,Javac 编译器完成编译,Java虚拟机完成解析。Javac 编译器:程序代码经过
词法分析、
语法分析、
抽象语法树、
遍历语法树生成字节码指令流的过程。 Java虚拟机的解析器负责解析字节码,执行器负责执行。因此,Java 程序的编译就是半独立的实现。