4.认识JVM-编译器

目录

1.认识JVM之Classfile:https://www.cnblogs.com/nuti/p/16270652.html

2.认识JVM之类加载机制:https://www.cnblogs.com/nuti/p/16270672.html

3.认识JVM之运行时数据区: https://www.cnblogs.com/nuti/p/16270703.html

4.认识JVM之编译器: https://www.cnblogs.com/nuti/p/16270741.html

5.认识JVM之垃圾收集器: https://www.cnblogs.com/nuti/p/16270755.html

6.认识JVM之JVM内存模型: https://www.cnblogs.com/nuti/p/16270816.html

 

书接上文这次轮到了编译器 https://www.cnblogs.com/nuti/p/16270703.html

0
hotspot图上只写了jit编译器,其实还有interpretr解释器
0
编译之后的class文件如何交给计算机执行 就是通过interpreter或者jit去执行翻译
不要和javac混淆。当然他们都是做的解释器和编译器
javac的对象是java的源码文件
现在要讲的是面向的是字节码文件
javac编译器将源码文件编译成class文件[我们把这里的编译称为前期编译],交给JVM运行,因为JVM只能认识class字节码文件。同时在不同的操作系统上安装对应版本的JDK,里面包含了各自屏蔽操作系统底层细节的JVM,这样同一份class文件就能运行在不同的操作系统平台之上,得益于JVM。这也是Write Once,Run Anywhere的原因所在
最终JVM需要把字节码指令转换为机器码,可以理解为是0101这样的机器语言,这样才能运行在不同的机器上,那么由字节码转变为机器码是谁来做的呢?说白了就是谁来执行这些字节码指令的呢?这就是执行引擎里面的解释执行器和编译器所要做的事情
翻译的方式有2种 可以java -version看一下
0
 

1.Interpreter

Interpreter,解释器逐条把字节码翻译成机器码并执行,跨平台的保证。
刚开始执行引擎只采用了解释执行的,但是后来发现某些方法或者代码块被调用执行的特别频繁时,就会把这些代码认定为“热点代码”。那些热点代码平时不怎么变动而且使用还多,那么就有了下面的jit编译器
 

2.JIT

Just-In-Time compilation(JIT),即时编译器先将字节码编译成对应平台的可执行文件,运行速度快。即时编译器会把这些热点代码编译成与本地平台关联的机器码,并且进行各层次的优化,保存到内存中
 

2.1.c1/c2编译器

HotSpot虚拟机里面内置了两个JIT:C1和C2
  • C1也称为Client Compiler,适用于执行时间短或者对启动性能有要求的程序
  • C2也称为Server Compiler,适用于执行时间长或者对峰值性能有要求的程序
Java7开始,HotSpot会使用分层编译的方式
也就是会结合C1的启动性能优势和C2的峰值性能优势,热点方法会先被C1编译,然后热点方法中的热点会被C2再次编译
这个在程序运行的时候将热点代码解释成可执行的文件 这样其实会抢占cpu资源 就往下看看aot
 

2.2.Aot编译器

在Java9中,引入了AOT(Ahead of Time)编译器
AOT是在程序运行之前,将字节码转换为 机器码,这也也就避免了cpu资源的消耗
但是他也是有弊端的
基于类层次分析的完全虚方法内联,AOT 编译无法得知程序运行时的信息
基于程序profifile的投机性优化(并非硬性限制,我们可以通过限制运行范围,或者利用上一次运行的程序profifile来绕开这两个限制)
 

2.3.GraalVM编译器

这个还是在初始阶段,但是已经被spring native和dubbo native所使用
使用GraalVm可以是项目启动时间到达毫秒级,内存能减少(大概能减少二十分之1)
在Java10中,新的JIT编译器Graal被引入。它是一个以Java为主要编程语言,面向字节码的编译器。跟C++实现的C1和C2相比,模块化更加明显,也更加容易维护。
Graal既可以作为动态编译器,在运行时编译热点方法;也可以作为静态编译器,实现AOT编译,可以作为jvm的一个编译器 也能单独使用。
 
 
posted @ 2022-05-14 17:20  Nuti  阅读(72)  评论(0编辑  收藏  举报