JVM-JIT

源自网络

前端编译主要指与源语言有关但与目标机无关的部分,包括词法分析、语法分析、语义分析与中间代码生成。

后端编译主要指与目标机有关的部分,包括代码优化和目标代码生成等。

http://www.hollischuang.com/archives/2322

JVM运行原理

源自网络

Java程序最初是通过解释器(Interpreter)进行解释执行的,当虚拟机发现某个方法或代码块的运行特别频繁时,就会把这些代码认定为“热点代码”。为了提高热点代码的执行效率,在运行时,虚拟机将会把这些代码编译成与本地平台相关的机器码,并进行各种层次的优化,完成这个任务的编译器称为即时编译器(Just In Time Compiler,下文统称JIT编译器)  =》C1 C2/ Client Complier和Server Complier

为什么HotSpot虚拟机要使用解释器与编译器并存的架构?

源自网络

解释器与编译器两者各有优势:当程序需要迅速启动和执行的时候,解释器可以首先发挥作用,省去编译的时间,立即执行。在程序运行后,随着时间的推移,编译器逐渐发挥作用,把越来越多的代码编译成本地代码之后,可以获取更高的执行效率。当程序运行环境中内存资源限制较大(如部分嵌入式系统中),可以使用解释器执行节约内存,反之可以使用编译执行来提升效率。此外,如果编译后出现“罕见陷阱”,可以通过逆优化退回到解释执行。

在Java HotSpot VM内部,实际上有两种单独的JIT编译器模式,分别称为C1和C2。 C1用于需要快速启动和具有良好优化的应用; GUI应用程序通常是此编译器的理想选择。另一方面,C2最初是用于长时间运行的(主要是服务器端)应用程序。在某些Java SE 7更高版本之前,分别使用-client和-server开关可以使用这两种模式。

两种编译器模式使用不同的技术进行JIT编译,并且对于同一Java方法,它们可以输出非常不同的机器代码。但是,现代Java应用程序通常可以同时使用两种编译模式。为了利用这一事实,从某些Java SE 7更高版本开始,提供了一个称为分层编译的新功能。此功能在开始时使用C1编译器模式,以提供更好的启动性能。一旦正确地对应用程序进行了预热,C2编译器模式将接管其工作,以提供更具攻击性的优化,并且通常提供更好的性能。随着Java SE 8的到来,分层编译现已成为默认行为。

OSR 栈上替换(On Stack Replacement)

程序中的代码只有是热点代码时,才会编译为本地代码,那么什么是热点代码呢?

运行过程中会被即时编译器编译的“热点代码”有两类:1、被多次调用的方法。

2、被多次执行的循环体。

局部时间性、局部空间性

计数方式

源自网络

JVM基于计数器的热点探测:采用这种方法的虚拟机会为每个方法(甚至是代码块)建立计数器,统计方法的执行次数,如果执行次数超过一定的阀值,就认为它是“热点方法”。这种统计方法实现复杂一些,需要为每个方法建立并维护计数器,而且不能直接获取到方法的调用关系,但是它的统计结果相对更加精确严谨。

提供了方法调用计数器(记录一个方法被调用次数的计数器)和回边计数器(记录方法中的for或者while的运行次数的计数器)

逃逸分析

在编译期间,JIT会对代码做很多优化。其中有一部分优化的目的就是减少内存堆分配压力,其中一种重要的技术叫做逃逸分析

逃逸分析(Escape Analysis)是目前Java虚拟机中比较前沿的优化技术。这是一种可以有效减少Java 程序中同步负载和内存堆分配压力的跨函数全局数据流分析算法。通过逃逸分析,Java Hotspot编译器能够分析出一个新的对象的引用的使用范围从而决定是否要将这个对象分配到堆上。

逃逸分析的基本行为就是分析对象动态作用域:当一个对象在方法中被定义后,它可能被外部方法所引用,例如作为调用参数传递到其他地方中,称为方法逃逸。

你可能感兴趣的:(JVM-JIT)