Java作为一种高级编程语言以其较高的可移植性被广泛使用在各个平台。那么它底层运行的原理是什么?

认识JRE和JDK

JRE(Java Runtime Environment):Java运行时环境。Java的所有执行都离不开JRE。JRE包含了Java虚拟机和Java核心类库等。

JDK(Java Development Kit):Java开发工具包。同样包含了JRE,并且还附带了一系列开发,诊断工具。

Java虚拟机具体是如何运行Java字节码的

  1. 执行Java代码首先要将它编译成class文件加载到Java虚拟机中。
  2. 加载后的Java类会被存放于方法区(Method Area)中。
  3. 实际运行时虚拟机会执行方法区中的代码。
  4. Java虚拟机会在内存中划分出堆和栈来存储运行时数据。
    • Java虚拟机会将栈细分为:
      1. 面向Java方法的Java方法栈(也叫Java虚拟机栈)。
      2. 面向本地方法的本地方法栈(用C++写的Native方法)。
      3. 以及存放各个线程执行位置的PC寄存器。
img
  1. 运行过程当中,每当调用进入一个Java方法,Java虚拟机会在当前线程的Java方法栈中生成一个栈帧,用于存放局部变量以及字节码的操作数。这个栈帧大小是提前计算好的,而且Java虚拟机不要求栈帧在内存空间里连续分布。

  2. 退出执行方法时,不管是正常还是异常都会弹出当前线程栈帧,并舍弃。

  3. 硬件执行是需要Java虚拟机将字节码翻译成为机器码:

    1. 解释执行:逐条将字节码翻译成为机器码并执行。优势:无需等待编译。
    2. 即时编译(Just-In-Time Compilation, JIT):即将一个方法中包含的所有字节码编译成为机器码后再执行。优势:实际运行速度更快
    img

HotSpot采用的是混合模式:会对热点代码进行即时编译(JIT)。

Java虚拟机的运行效率

二八定律:即时编译建立在程序符合二八定律的假设上,即百分之二十的代码占据了百分之八十的计算资源。

对于大部分不常用的代码,无需耗费时间将其编译成机器码,而是采取解释执行。

对于近占据小部分的热点代码,可以将其编译成为机器码。

即时编译器:C1,C2和Graal(Java10引入)

C1编译器:又叫Client编译器,面向的是对启动性能有要求的客户端GUI程序,采用的优化手段较少。

C2编译器:又叫Server编译器,面向的是对峰值性能有要求的服务器端程序,采用的优化手段较为复杂。编译时间长,但是生成的代码执行效率高。

Java7开始HotSpot默认采用的是分层编译:热点方法首先会被C1编译,而后热点中的热点会被C2进一步编译。

总结

  1. Java虚拟机Jvm:提供了可移植性:一次书写,处处运行。
  2. 代替我们管理了内存。
  3. 为了提高效率采用了混合编译。