java性能优化--JIT即时编译器

311 阅读4分钟

持续创作,加速成长!这是我参与「掘金日新计划 · 6 月更文挑战」的第17天,点击查看活动详情

最近因为要离职的原因,思绪比较远,原本以为本次更文进行不下去了,但是又闲的没有事情做,看了看更文的活动时间,又决定继续更起来了,要不也是在发呆。本篇文章继续学习java性能优化相关的基础知识。

JIT编译器

JIT编译器(Just In Time),即时编译器,是jvm的核心。作为用户的我们,绝大多数情况下,只需要对编译器做适当的调优即可。

语言类型

CPU只能执行特定的指令,我们可以称这种指令为汇编码二进制码,所以在CPU上运行的语言都必须翻译成这种指令。

常见的语言可以分成编译型解释型

  • 编译型:我们常常听到的C++,就是编译型语言。先写代码,然后通过静态编译的方式将代码翻译成二进制形式进行交付。

  • 解释型:如PHP,就是解释型语言。只要服务器上有解释器,执行程序时,解释器会将代码解释称为二进制代码。

每种语言各有各的长处和不足:

语言类型优点缺点
解释型可移植性。只要服务器有相应的解释器,就可以使得程序运行。解释器将相同的源代码解释成不同的机器码。较慢,逐行解释导致不能获取足够的信息。好的编译器会对编译后的二进制代码做顺序等等一系列的优化。而解释型则没有足够的信息去优化这些二进制代码。
编译型运行效率高,编译后,对二进制码进行了优化,同时脱离编译器也可以运行。程序不能跨平台源代码不能跨平台

java是什么类型?

前面说了那么多,那么作为java开发的你一定很想知道,java属于哪种类型?

java采用一种中间方式。代码进行编译,但不是编译成CPU支持的机器码,而是编译成一种使用JVM运行的汇编语言(java字节码),然后程序运行时,JVM会对这个汇编语言进行解释,编译成平台支持的二进制码。

因为这个解释的过程是在程序运行时,所以被称为 即使编译(JIT)

热点编译

对于一个运行当中的程序,经常被使用的代码通常只有一部分,应用的性能取决于这些被经常运行的代码,而这些经常被运行的代码,我们称之为热点,运行的越多,则越热。

JVM在执行代码时,通常不会编译所有代码:

  • 理由一:如果代码只会执行一次,那么解释运行时间会远小于优先编译所耗费的时间。而热点代码,如循环等,优先编译就是必要的,因为其运行更快,多次运行的时间比优先编译的时间要短。编译器能够分辨哪些代码会被频繁调用,进行编译。

  • 理由二:针对执行频繁的代码,jvm会对其逐渐了解,从而进行大量的优化操作。

    下面解释下上述的第二个原因: 比如调用equals方法,有如下伪代码

    boolean flag = obj1.equals(obj2)
    

    在比较之前,会去获取当前obj1的类型,该过程是比较耗时的。当随着多次执行这条语句,发现obj1每一次都是java.lang.String,于是jvm会直接将代码编译成String.equals(),从而通过编译的方式跳过查找obj1类型的过程,达到提升效率的目的。

    当然,obj1有可能咋下一次变成其他类型,这就要求jvm有处理这种可能的能力,重新编译代码。

总结

  • 语言种类分成编译型和解释型。而java采取了编译型的快速性能和解释型的跨平台特性。
  • java文件被编译成java字节码,在jvm当中被进一步编译成汇编语言。
  • jvm将java字节码编译成汇编语言时,使用了大量的优化。