阿里巴巴Java性能调优实战:深入JVM即时编译器JIT,优化Java编译

createh54个月前 (12-22)技术教程42

深入JVM即时编译器JIT,优化Java编译

然而许多 Java 开发人员对 JIT 编译器的了解并不多,不深挖其工作原理,也不深究如何检 测应用程序的即时编译情况,线上发生问题后很难做到从容应对。

类编译加载执行过程

类编译

在编写好代码之后,我们需要将 .java 文件编译成 .class 文件,才能在虚拟机上正常运行代 码。文件的编译通常是由 JDK 中自带的 Javac 工具完成,一个简单的 java 文件,我们可 以通过 javac 命令来生成 .class 文件。

下面我们通过 javap反编译来看看一个 class 文件结构中主要包含了哪些信息:

看似一个简单的命令执行,前期编译的过程其实是非常复杂的,包括词法分析、填充符号 表、注解处理、语义分析以及生成 class 文件,这个过程我们不用过多关注。只要从上图中 知道,编译后的字节码文件主要包括常量池和方法表集合这两部分就可以了。

类加载

当一个类被创建实例或者被其它对象引用时,虚拟机在没有加载过该类的情况下,会通过类 加载器将字节码文件加载到内存中。

类连接

类在加载进来之后,会进行连接、初始化,最后才会被使用。在连接过程中,又包括验证、 准备和解析三个部分。

类初始化


即时编译

即时编译器类型

在 HotSpot 虚拟机中,内置了两个 JIT,分别为 C1 编译器和 C2 编译器,这两个编译器的 编译过程是不一样的。

第 0 层:程序解释执行,默认开启性能监控功能(Profiling),如果不开启,可触发第 二层编译;

第 1 层:可称为 C1 编译,将字节码编译为本地代码,进行简单、可靠的优化,不开启 Profiling;

第 2 层:也称为 C1 编译,开启 Profiling,仅执行带方法调用次数和循环回边执行次数 profiling 的 C1 编译;

第 3 层:也称为 C1 编译,执行所有带 Profiling 的 C1 编译;

第 4 层:可称为 C2 编译,也是将字节码编译为本地代码,但是会启用一些编译耗时较长的优化,甚至会根据性能监控信息进行一些不可靠的激进优化。

热点探测

在 HotSpot 虚拟机中的热点探测是 JIT 优化的条件,热点探测是基于计数器的热点探测, 采用这种方法的虚拟机会为每个方法建立计数器统计方法的执行次数,如果执行次数超过一 定的阈值就认为它是“热点方法” 。

虚拟机为每个方法准备了两类计数器:方法调用计数器(Invocation Counter)和回边计 数器(Back Edge Counter)。在确定虚拟机运行参数的前提下,这两个计数器都有一个 确定的阈值,当计数器超过阈值溢出了,就会触发 JIT 编译。

编译优化技术

JIT 编译运用了一些经典的编译优化技术来实现代码的优化,即通过一些例行检查优化,可 以智能地编译出运行时的最优性能代码。今天我们主要来学习以下两种优化手段:

1. 方法内联

那么对于那些方法体代码不是很大,又频繁调用的方法来说,这个时间和空间的消耗会很 大。方法内联的优化行为就是把目标方法的代码复制到发起调用的方法之中,避免发生真实 的方法调用。

2. 逃逸分析

逃逸分析(Escape Analysis)是判断一个对象是否被外部方法引用或外部线程访问的分析 技术,编译器会根据逃逸分析的结果对代码进行优化。

栈上分配

然后,我们分别设置 VM 参数:Xmx1000m -Xms1000m -XX:-DoEscapeAnalysis - XX:+PrintGC 以及 -Xmx1000m -Xms1000m -XX:+DoEscapeAnalysis -XX:+PrintGC, 通过之前讲过的 VisualVM 工具,查看堆中创建的对象数量。

然而,运行结果却没有达到我们想要的优化效果,也许你怀疑是 JDK 版本的问题,然而我 分别在 1.6~1.8 版本都测试过了,效果还是一样的:

(-server -Xmx1000m -Xms1000m -XX:-DoEscapeAnalysis -XX:+PrintGC)

(-server -Xmx1000m -Xms1000m -XX:+DoEscapeAnalysis -XX:+PrintGC)

这其实是因为由于 HotSpot 虚拟机目前的实现导致栈上分配实现比较复杂,可以说,在 HotSpot 中暂时没有实现这项优化。随着即时编译器的发展与逃逸分析技术的逐渐成熟, 相信不久的将来 HotSpot 也会实现这项优化功能。

锁消除

标量替换

总结

相关文章

9000字,通俗易懂的讲解下Java注解

对于Java注解,我咨询过一些身边的人,很多人表示:知道怎么用,不熟悉不知道你是不是这样?在我没有系统性的学习一边注解的时候,我也是如此,在我花时间学习过注解之后,我觉得,对于注解,最重要的在于理解,...

深入理解Java虚拟机之自己编译JDK

题外话最近在阅读《深入理解Java虚拟机》,其中有一小节实战是自己编译JDK,实际操作下来后遇到问题不少,为此特地记录,也希望可以给大家带来一些参考!前置准备平台及工具: Windows 10 + W...

带你入门Java之每日3分钟Java——编写你的第一个Java程序

接着上期带你入门Java之每日3分钟Java——初识Java我们在已经完成Java运行环境配置的前提下,开始着手学习如何编写Java我们的第一个程序。创建第一个Java工程项目首先我们要进入安装好的J...

Java反编译工具 java反编译工具并修改代码

编译和反编译编程语言分成高级语言和低级语言。低级语言如机器语言、汇编语言。这类语言直接用计算机指令编写命令,不需要编译。这些语言机器能看到懂,但是程序员读起来很费劲。而我们平时经常用的语言C、Java...