前言
这几天重新研究了一下内存模型、内存屏障,在学习内存屏障的时候,了解了lock前缀指令,为了编译出lock前缀指令,于是去学了一下字节码指令。因为还要添加一些运行参数,于是今天又看了一下午JVM的编译问题。知识一环套一环,现在内存屏障这一块还没搞完。这可能也正是自学乐趣之所在,知识无限延展,层层连贯,于是晚上就整理了一下关于java编译方面总结。
Java代码如何运行
我们写的Java代码是高级语言,机器肯定是读不懂的。所以我们需要将它转换成机器能读懂的机器语言(机器码)。
转换工作主要分为以下几个步骤:
前端编译器
javac就是前端编译器,可以将java文件编译成字节码组成的class文件。
java代码如下:
public class Info { public static void main(String[] args) { int a = 1; System.out.println(a); } }
执行javac Info.java生成Info.class文件,再使用javap -c Info.class来查看其中的字节码。
class中字节码内容如下:
解释器和即时编译器
我们通过javac将java文件编译成class文件,当jvm启动加载class,需要逐条执行字节码指令来完成程序功能。但是程序的执行还是得在机器上,但是机器是不认识字节码的,所以我们需要将字节码转换成机器码,这样才能让机器执行程序。
什么是机器码?
机器码就是用二进制代码表示的计算机能直接识别和执行的一种机器指令的集合。
而解释器和即时编译器(Just In Time Compiler,JIT)就是JVM中将字节码转化为机器码的工具。
解释器
解释器是一行一行地将字节码解析成机器码,解释到哪就执行到哪,狭义地说,就是for循环100次,你就要将循环体中的代码逐行解释执行100次。当程序需要迅速启动和执行时,解释器可以首先发挥作用,省去编译的时间,立即执行。
即时编译器(JIT)
即时编译器按照我的理解就是:以方法为单位,将热点代码的字节码一次性转为机器码,并在本地缓存起来的工具。避免了部分代码被解释器逐行解释执行的效率问题。
即时编译器分为两种,Client