JVM解决什么问题
- JVM在我的理解与CLR是一回事,本身还是为了解决java代码无法直接编译为机器码。
- 对标C#,类型的动态推导等功能是在运行时做的,因此无法做到AOT。就需要虚拟机来做这个事情了。
- 如虚函数实现多态这样的情况,JVM中可以简单的获得当前应该调用哪个实现函数,从而优化代码的执行。
- 最后,使用虚拟机可以做到代码不考虑具体在哪个平台运行的问题,实现跨平台使用。
JVM的运行
五个部分
- Java 虚拟机将运行时内存区域划分为五个部分,分别为方法区、堆、PC 寄存器、Java 方法栈和本地方法栈。Java 程序编译而成的 class 文件,需要先加载至方法区中,方能在 Java 虚拟机中运行。
- 本质上所有的代码执行都是JVM构建栈帧,这个东西在C#、java、lua上都是一样的。
- 估计java的寄存器也是JVM自己的,而不是真正硬件的寄存器。
解释执行器和即时编译器(JIT)
- 前者对于字节码逐条编译为机器码,然后运行。
- 后者对于一个函数整体编译为机器码,然后运行。
HotSpot的执行
HotSpot 采用了多种技术来提升启动性能以及峰值性能,刚刚提到的即时编译便是其中最重要的技术之一。
即时编译建立在程序符合二八定律的假设上,也就是百分之二十的代码占据了百分之八十的计算资源。
对于占据大部分的不常用的代码,我们无需耗费时间将其编译成机器码,而是采取解释执行的方式运行;另一方面,对于仅占据小部分的热点代码,我们则可以将其编译成机器码,以达到理想的运行速度。
JIT
- Hotspot中有C1、C2、Graal三个JIT编译器。
之所以引入多个即时编译器,是为了在编译时间和生成代码的执行效率之间进行取舍。C1 又叫做 Client 编译器,面向的是对启动性能有要求的客户端 GUI
程序,采用的优化手段相对简单,因此编译时间较短。C2 又叫做 Server 编译器,面向的是对峰值性能有要求的服务器端程序,采用的优化手段相对复杂,因此编译时间较长,但同时生成代码的执行效率较高。
从 Java 7 开始,HotSpot 默认采用分层编译的方式:热点方法首先会被 C1 编译,而后热点方法中的热点会进一步被 C2 编译。