从java文件到字节码

2019-09-10 15:52:37 浏览数 (1)

本文来说一下,我们开发好的.java文件是源码文件,并不能交给机器直接执行,需要将其变成字节码甚至是机器码文件。那么静态编译器是如何把源码转化成字节码的呢?

下图为.java源码转化为字节码的过程。

词法解析就是通过空格分隔出单词、操作符、控制符等信息,将其形成token信息流,传递给语法解析器;在语法解析时,把词法解析得到的token信息流按照Java语法规则组装成一个语法树。

如上图虚线框中所示;在语义分析阶段,需要检查关键字的使用是否合理、类型是否合理、作用域是否正确等。当语义分析完成之后,即可以生成字节码。

字节码必须通过类加载过程加载到JVM环境中后,才可以执行。

字节码执行的三种模式
  1. 解释执行
  2. JIT编译执行
  3. JIT编译与解释混合执行(主流JVM默认模式)
何为JIT编译?
  • 动态编译(dynamic compilation)指的是“在运行时进行编译”;与之相对的是事前编译(ahead-of-time compilation,简称AOT),也叫静态编译(static compilation)。
  • JIT编译(just-in-time compilation)狭义来说是当某段代码即将第一次被执行时进行编译,因而叫“即时编译”。JIT编译是动态编译的一种特例。JIT编译一词后来被泛化,时常与动态编译等价;但要注意广义与狭义的JIT编译所指的区别。
  • 自适应动态编译(adaptive dynamic compilation)也是一种动态编译,但它通常执行的时机比JIT编译迟,先让程序“以某种式”先运行起来,收集一些信息之后再做动态编译。这样的编译可以更加优化。

混合执行模式的优势在于解释器在启动时先解释执行,省去编译时间。随着时间推进,JVM通过热点代码统计分析,识别高频的方法调用、循环体、公共模块等。JIT的作用就是将Java字节码动态低编译成可以直接发送给处理器指令执行的机器码。大致流程如下:

注意:解释执行与编译执行在线上环境微妙的辩证关系。机器在热机状态可以承受的负载大于冷机状态(刚刚启动的时候),如果以热机状态的流量进行切流,可能会导致处于冷机状态的服务器因无法承受流量而假死。在生产环境发布过程中,以分批的方式进行发布,根据机器数量划分成多个批次,建议每个批次的机器数之多占到整个集群的12.5%(1/8)。曾经有这样的故障案例:某程序员在发布平台进行分批发布,在输入发布总批次数的时候,误填写成分两批发布。如果是热机状态,在正常情况下一半的机器可以勉强承载流量,但是由于刚刚启动的JVM均是解释执行,还没有进行热点代码统计和JIT动态编译,导致机器启动之后,当前1/2发布成功的服务器马上全军覆没,此次故障说明了JIT的存在。

下篇说类加载过程,敬请期待!

0 人点赞