Graal 编译器

Graal 编译器是一个用 Java 编写的动态编译器,可将字节码转换为机器代码。Graal 即时 (JIT) 编译器与 Java HotSpot 虚拟机和 GraalVM 集成。有关更多信息,请参阅 《Java 虚拟机指南》以及作为虚拟机的 GraalVM 部分。(Graal JIT 编译器的开源代码可在 GitHub 上获取。)

编译器优势 #

Graal JIT 编译器通过独特的代码分析和优化方法,为在 Java 虚拟机 (JVM) 上运行的应用程序提供优化的性能。它包括多种优化算法(称为“阶段”),例如激进内联、多态内联等。

Graal 编译器可以为高度抽象的程序带来性能优势。例如,它包含一个部分逃逸分析优化,可以消除某些对象昂贵的分配。有关更多信息,请参阅 GraalVM GitHub 存储库中 CEOptimization enum 中的值 PartialEscapeAnalysis。此优化确定新对象何时可在编译单元外部访问,并且仅在“逃逸”编译单元的路径上分配它(例如,如果对象作为参数传递、存储在字段中或从方法返回)。此方法通过减少堆分配的数量,可以极大地提高应用程序的性能。使用更现代的 Java 特性(如 Streams 或 Lambdas)的代码将看到更大的性能改进,因为此类代码涉及大量此类非逃逸或部分逃逸对象。受 I/O 或编译器无法消除的内存分配等特征限制的代码,性能改进将较少。有关性能调优的更多信息,请参阅 Graal JIT 编译器配置

图编译 #

为了在与基于 JVM 的宿主语言相同的运行时中运行客户编程语言(即 JavaScript、Python 和 Ruby),编译器使用一种独立于语言的中间图表示,介于源语言和要生成的机器代码之间。(有关语言互操作性的更多信息,请参阅互操作性。)

该图可以用相同的方式表示不同语言的相似语句,例如“if”语句或循环,这使得在同一个应用程序中混合语言成为可能。Graal 编译器随后可以对该图执行独立于语言的优化并生成机器代码。

诊断数据 #

如果编译器抛出未捕获的异常,则编译通常会被丢弃,并继续执行。Graal 编译器可以生成诊断数据(例如即时表示图),这些数据可以随错误报告一起提交。这可以通过 -Djdk.graal.CompilationFailureAction=Diagnose 选项启用。诊断输出的默认位置是进程当前工作目录下的 graal_dumps/ 目录,但可以通过 -Djdk.graal.DumpPath 选项更改。在 JVM 关闭期间,包含诊断数据的存档位置会打印到控制台。

此外,可以使用 -Djdk.graal.Dump 选项为 Graal 编译器执行的任何编译生成诊断数据。这将为编译器编译的每个方法生成诊断数据。

要优化生成诊断数据的方法集,请使用 -Djdk.graal.MethodFilter=<class>.<method> 选项。例如,-Djdk.graal.MethodFilter=java.lang.String.*,HashMap.get 将仅为 java.lang.String 类中的方法以及非限定名为 HashMap 的类中名为 get 的方法生成诊断数据。

联系我们