`

深入理解JVM—字节码编译机制

 
阅读更多

 

对于写代码的人都知道,我们一般的程序编译过程都有语法分析、词法分析等一系列检查操作,然后生成对应的机器码或者字节码。对于C++来说,其编译过程可使用下图表示

 

深入理解JVM—字节码编译机制 - 一线天色 天宇星辰 - 一线天色 天宇星辰

 当然我们知道还有一部分语言是使用解释器工作的,其标准流程如下:

 

深入理解JVM—字节码编译机制 - 一线天色 天宇星辰 - 一线天色 天宇星辰

 我们大学的时候,很多老师会告诉我们,

java是一门解释性语言,但是Java笔传统解释器执行做了一定的优化,它不是对源码文件直接的解释,而是对通过优化后生成的字节码文件作解释操作,其流程如下:

 

深入理解JVM—字节码编译机制 - 一线天色 天宇星辰 - 一线天色 天宇星辰

 Java

执行过程中首先对符合Java语言规范和虚拟机规范的源码进行一次编译操作,生成机器无关性的符合JVM规范的字节码文件,然后在JVM运行时再做解释操作,进而完成Java代码从源码到机器指令的执行,其流程图如下:

 

深入理解JVM—字节码编译机制 - 一线天色 天宇星辰 - 一线天色 天宇星辰

 但实际上,

Java并不是一门纯粹的解释执行的语言,从JDK1.2之后,JVM在运行之前会对字节码和运行环境做一次检查,如果运行的JVMClient模式,则继续使用解释执行模式,如果是Server模式,CPU超过4个逻辑核心,内存超过4GBJVM会选择性的将频率使用较高的字节码启用JIT编译,编译后直接生成机器相关的字节码,这样下次再次执行这段代码的时候效率就会高很多。从JDK1.2(又称java2)之后,其流程可用下图表示:

 

深入理解JVM—字节码编译机制 - 一线天色 天宇星辰 - 一线天色 天宇星辰

 对于字节码的处理分成了

2个分支,对于一部分 代码使用JIT编译器生成对应的机器代码,而对于另一部分则继续使用解释执行的方式。

下面我们来逐个看一下每个步骤JVM所做的事情。

首先我们要提到的肯定是生成机器无关性的字节码文件爱你,那字节码是如何生成的呢?

我们都知道是通过Java的编译器编译生成。Java编译器的主要任务就是将符合java 语言规范的源码编译为符合java虚拟机规范的字节码文件,如果输入的Java源码不符合规则,则报告错误。

平时我们最熟悉的莫过于Sun公司的JDKSun JDK中的源码编译器是javac,该编译器是使用java 编写的,从某种程度上实现了java的自举(bootstrap),而真正实现自举还得结合Java实现的JVM

其实我们实际工作中使用的最多的ECJ(Eclipse Compiler for Java)的编译器

编译器在执行过程中其实就是根据Java的语法规则,将语言中隐含的结构表现出来。

Javac的工作流程如下图所示:

 

深入理解JVM—字节码编译机制 - 一线天色 天宇星辰 - 一线天色 天宇星辰

 通过解析与输入到符号表,注解处理、分析与代码生成几个步骤。其中分析与代码生成包含以下几方面:

1、  属性标注与检查(Attr and Check

2、  数据流分析(Flow

3、  泛型转换(TransType)(将泛型转换为实际的裸体类型(raw type)

4、  解除语法糖(Lower

5、  生成字节码文件(Gen

而解析包含词法分析和语法分析,词法分析主要是通过com.sun.tools.javac.parser.Scanner、手写的ad-hoc方式构造的词法分析器将字符序列转换为标准词法的token序列。语法分析是使用com.sun.tools.javac.parser.Parser、递归下降和运算符优先程式的语法分析器根据语法将词法分析器生成的token序列生成抽象语法树。语法分析后所有的步骤都在抽象语法树上进行。下图是词法分析和语法分析的一个示意图。

int y = x + 1;对应的词法分析如下:

 

深入理解JVM—字节码编译机制 - 一线天色 天宇星辰 - 一线天色 天宇星辰
 int y = x + 1;对应的语法分析如下:

 

深入理解JVM—字节码编译机制 - 一线天色 天宇星辰 - 一线天色 天宇星辰

 语法分析完毕后编译器将通过

com.sun.tools.javac.comp.Enter将每个编译单元的抽象语法树顶节点放在待处理列表中,然后逐个处理列表中的节点。处理完成的类符号被输入到外围作用域的符号表中。然后逐个确定类的参数(针对泛型类型)、超类型和接口、根据需要添加默认构造器,将类中出现的符号舒服到自身的符号表中、分析和校验代码中的注解(annotation)

完成类定以前的代码如下:

package com.yhj.test;

/**

 * @Described:测试用例

 * @author YHJ create at 2012-3-上午10:25:18

 * @FileNmae com.yhj.test.TestCase.java

 */

public class TestCase {

}

完成类定义以后的代码如下

package com.yhj.test;

/**

 * @Described:测试用例

 * @author YHJ create at 2012-3-上午10:25:18

 * @FileNmae com.yhj.test.TestCase.java

 */

public class TestCase {

   public TestCase() {

      super();

   }

}

我们可以很清楚的看到添加了一个默认的构造器。

接下来要做的事情是注解处理,是通过com.sun.toolsjavac.processing.JavaProcessingEnviroment进行处理的。我们都知道注解是JDK1.6以后新加的特性,也就是支持注解的最低JDK版本是JDK6,通过注解处理,可以读取到语法树中的所有元素,包含注释,可以更改类类型的定义,可以创建新的类型。。。而这一系列操作又可以重新的解析和写入符号表,如下图所示:

 

深入理解JVM—字节码编译机制 - 一线天色 天宇星辰 - 一线天色 天宇星辰

 如下图所示,代码直接处理前如下:

 

深入理解JVM—字节码编译机制 - 一线天色 天宇星辰 - 一线天色 天宇星辰

 代码注解处理后如下图所示

 

深入理解JVM—字节码编译机制 - 一线天色 天宇星辰 - 一线天色 天宇星辰

 注解处理完成,接着要做的事情就是标注和检查

(Attr and check),主要通过类com.sun.tools.javac.comp.Attrcom.sun.tools.javac.comp.Check完成,它是语义分析

的一个步骤。这个过程主要做以下事情:

1、  将语法树中的名字、表达式等元素与变量、方法、类型等联系到一起

2、  检查变量使用前是否已经声明

3、  推导泛型方法的类型参数

4、  检查类型匹配

5、  进行常量折叠

如下图所示,标注前的代码如下:

 

深入理解JVM—字节码编译机制 - 一线天色 天宇星辰 - 一线天色 天宇星辰

 标注后的代码形态如下:

 

深入理解JVM—字节码编译机制 - 一线天色 天宇星辰 - 一线天色 天宇星辰

 标注完成之后进行数据流分析,主要是通过类

com.sun.tools.javac.comp.Flow这个类来完成的,它也是语义分析的一个步骤,主要做以下几件事情:

1、  检查所有语句是否都可达

2、  检查所有的checked exception都被捕获或者抛出

3、  检查变量的确定性赋值

a)         所有局部变量在使用前都必须有确定的赋值

b)         有返回值的方法必须有确定性的返回值

4、  检查变量的确定性不重复赋值

a)         保证final类型不能重复赋值

接下来要做的事情就是转换类型(TransTypes),是通过com.sun.tools.javac.comp.TransTypes处理的,这也是解除语法糖的一个重要步骤,如想泛型转换为普通的Java代码同时插入必要的类型转换代码,如下图所示,转换类型前代码如下:

 

深入理解JVM—字节码编译机制 - 一线天色 天宇星辰 - 一线天色 天宇星辰

 类型转换后代码如下:

 

深入理解JVM—字节码编译机制 - 一线天色 天宇星辰 - 一线天色 天宇星辰

 解除语法糖是通过

com.sun.tools.javac.comp.Lower来处理的,主要用于以下一些方面

1、  消除无用代码

a)         满足以下条件的被认为条件编译的无用代码

                                       i.              If语句的条件表达式是常量表达式的

                                     ii.              表达式的值为falsethen无用代码和为true条件下的else无用代码块

2、  将含有语法糖的语法树改写为含有简单语言结构的语法树

a)         内部类(具体的内部类和匿名内部类)

b)         字面常量

c)         断言

d)         自动拆装箱

e)         Foreach循环

f)          Enm类型的switch语句

g)         String类型的switchJava7新支持的语法)

h)         。。。

如下图所示,这是Lower之前的代码

 

深入理解JVM—字节码编译机制 - 一线天色 天宇星辰 - 一线天色 天宇星辰

 Lower

之后如下图所示

 

深入理解JVM—字节码编译机制 - 一线天色 天宇星辰 - 一线天色 天宇星辰

 Lower

之前的另外一段代码

 

深入理解JVM—字节码编译机制 - 一线天色 天宇星辰 - 一线天色 天宇星辰

 Lower

之后的代码

 

深入理解JVM—字节码编译机制 - 一线天色 天宇星辰 - 一线天色 天宇星辰

 解除语法糖之后就开始生成字节码文件,是通过

com.sun.tools.javac.jvm.Gen生成的,主要实现以下功能

1、  将实例成员初始化收集器收集到构造器中的<init>()

2、  将静态成员初始化器收集为<clinit>()

3、  将抽象语法树生成字节码

a)         后续遍历语法树

b)         进行少量的代码转换

                                       i.              String中的+被生产为StringBuilder操作

                                     ii.              X++/x—在条件允许时被优化为++x/--x

4、  从符号表生成Class文件

a)         生成字节码文件的结构信息

b)         生成元数据(包括常量池)

其流程如下

 

深入理解JVM—字节码编译机制 - 一线天色 天宇星辰 - 一线天色 天宇星辰
 

 执行过程如下图所示

 

深入理解JVM—字节码编译机制 - 一线天色 天宇星辰 - 一线天色 天宇星辰

 
至于具体是如何执行的?字节码的结构又是怎样的?

  • 大小: 61.6 KB
  • 大小: 39.5 KB
  • 大小: 43.6 KB
  • 大小: 44.6 KB
  • 大小: 90.1 KB
  • 大小: 49.3 KB
  • 大小: 30.2 KB
  • 大小: 38.7 KB
  • 大小: 10.3 KB
  • 大小: 49.6 KB
  • 大小: 57 KB
  • 大小: 44.1 KB
  • 大小: 20.3 KB
  • 大小: 32.1 KB
  • 大小: 47.7 KB
  • 大小: 47 KB
  • 大小: 47.7 KB
  • 大小: 61.2 KB
  • 大小: 26.6 KB
  • 大小: 46.8 KB
  • 大小: 40.1 KB
分享到:
评论

相关推荐

    jvm指令手册 +JVM必知必会,掌握虚拟机编译过程.rar

    Java语言使用Java虚拟机屏蔽了与具体平台相关的信息,使得Java语言编译程序只需生成在Java虚拟机上运行的目标代码(字节码),就可以在多种平台上不加修改地运行 《JVM必知必会》记录了对JVM的总结及学习笔记,详解...

    深入JVM内核—原理、诊断与优化

    资源名称:深入JVM内核—原理、诊断与优化 教程内容:课程简介:第一周初识JVMJVM分类...并介绍JVM字节码的执行方式。第三周常用JVM参数堆的分配参数栈分 资源太大,传百度网盘了,链接在附件中,有需要的同学自取。

    Bytecoder:用于JVM字节码的丰富域模型和用于解释和转换它的框架

    当前构建状态:高水平目标能够将JVM字节码交叉编译为JavaScript,WebAssembly,OpenCL和其他语言主要的编译目标是JavaScript和WebAssembly 充当LLVM的JVM字节码前端支持Java 8、9、10、11、12、13和14 与调试器工具...

    深入JVM内核 - 原理、诊断与优化

    并介绍JVM字节码的执行方式。 第三课 常用JVM参数 堆的分配参数 栈分配及实例讲解 server与client模式 调试跟踪参数 介绍常用的JVM参数,包括内存分配、堆栈分配、虚拟机运行模式以及调试跟踪参数。 第四课 GC的...

    j-j-jvm:用Java编写的JVM字节码解释器

    历史2009年,我在周末有一些空闲时间,决定尝试使用纯Java开发小型JVM解释器,该解释器可在J2ME CLDC 1.0平台中使用,因为该平台不支持ClassLoader,... JVM解释器不包含任何“ Poka-yoke”(防错)机制和字节码验证

    字节码文件结构详解.docx

    但随着工作过程中接触到了越来越多的基于 JVM 实现的语言如Groovy Kotlin Scala等,就深刻的理解到了 JVM 和 Java 的无关性,JVM 运行的不是 Java 程序,而是符合 JVM 规范的.class字节码文件。字节码是各种不同...

    深入Java虚拟机(原书第2版).pdf【附光盘内容】

     作者以易于理解的方式深入揭示了java虚拟机的内部工作原理,深入理解这些内容,将对读者更快速地编写更高效的程序大有裨益!  本书共分20章,第1-4章解释了java虚拟机的体系结构,包括java栈、堆、方法区、执行...

    简单实用JVM参数配置

    JVM是Java Virtual Machine(Java虚拟机)的缩写,JVM是一种用于计算设备的规范,它...JVM在执行字节码时,实际上最终还是把字节码解释成具体平台上的机器指令执行。编译虚拟机的指令集与编译微处理器的指令集非常类似

    免费开源!!Java字节码工程工具包

    Javassist(JAVA 编程助手)使 Java 字节码操作变得简单。它是Java中用于编辑字节码的类库;它使 Java 程序能够在运行时定义新类,并在 JVM 加载时修改类文件。与其他类似的字节码编辑器不同,Javassist 提供两个...

    JVM性能优化(五)源码图解jvm字节码

    一、前言 前面我们通过tomcat本身的参数以及jvm的参数对tomcat做了优化,详情查看:tomcat优化...这个时候,就需要通过查看编译好的class文件中的字节码,就可以找到答案。 我们都知道,java编写应用,需要先通过javac

    Java进阶教程解密JVM视频教程

    3. Java 程序从编译为字节码到加载到运行的全流程,各个阶段的优化处理;4. 了解 Java 内存模型相关知识,见识多线程并发读写共享数据时的问题和 Java 的解决方案。 适应人群 有一定的Java基础,希望提升 Java 内功...

    深入JVM即时编译器JIT,优化Java编译

    说到编译,我猜你一定会想到 .java 文件被编译成 .class 文件的过程,这个编译我们一般称为...由于机器无法直接运行 Java 生成的字节码,所以在运行时,JIT 或解释器会将字节码转换成机器码,这个过程就叫运行时编译。

    wombat-j:Clojure中内置的类似于方案的LISP。 (在运行时)编译为JVM字节码

    在Clojure中实现的类似于Scheme的LISP,在运行时将其编译为JVM字节码。 仔细检查后,可能会发现Wombat-J阅读器和编译器与Clojure中的阅读器和编译器之间异常相似。 确实是一个奇怪的巧合。 如果有的话,这表明这两...

    详细讲解了jvm在java中应用

    主要包含:JVM概述,内存结构...JVM 屏蔽了与操作系统平台相关的信息,从而能够让 Java 程序只需要生成能够在 JVM 上运行的字节码文件,通过该机制实现的跨平台性。即一次编译,处处执行;自动的内存管理,垃圾回收机制.

    组装:将WebAssembly编译为JVM和其他WASM工具

    Asmble是将代码编译为JVM字节码的编译器。 它还包含用于从命令行和JVM语言处理WASM代码的解释器和实用程序。 特征 WASM到JVM字节码编译器(无需运行时) WASM解释器(一次可逐步执行的指令) WASM二进制,WASM文...

    深入理解_Java_虚拟机 JVM_高级特性与最佳实践

    / 262 10.2.3 注解处理器 / 264 10.2.4 语义分析与字节码生成 / 264 10.3 Java语法糖的味道 / 268 10.3.1 泛型与类型擦除 / 268 10.3.2 自动装箱、拆箱与遍历循环 / 273 10.3.3 条件编译 / 275 10.4 实战:...

    Java知识,JVM面试资料

    JVM 的主要功能包括字节码解释和执行、垃圾回收、内存管理、即时编译等。下面是 JVM 的一些关键特性和应用场景: 跨平台性:JVM 的最重要的特性就是能够使得Java程序在不同的操作系统上运行。通过编译成统一的字节...

    jclasslib-win64-6-0-5.exe

    java jvm 字节码文件反编译工具

    bcdiff:命令行 JVM 字节码差异工具

    bcdiff 支持: 显示两个类文件(名称、标志、实现的接口...)之间元数据的差异, 在两个类文件之间以一种聪明的标签感知方式区分匹配方法(具有相同名称和签名的方法)的内容(字节码), 显示关于两个类文件( --...

    30道JVM综合面试题详解含答案(值得珍藏)

    JVM屏蔽了与具体操作系统平台相关的信息,使Java程序只需生成在Java虚拟机上运行的目标代码(字节码),就可以在多种平台上不加修改地运行。 JVM包含一套字节码指令集,一组寄存器,一个栈,一个垃圾回收堆和一个...

Global site tag (gtag.js) - Google Analytics