文章目录
- 说明
- Java程序执行流程
- JVM的语言无关性
- JVM的执行流程
- 执行引擎的两种行为:解释执行和编译
- 热点代码和热点代码探测方式
- 热点代码
- 热点代码探测方式
- 热点代码探测方式流程
- HotSpotVM内嵌两个JIT编译器
- Graal编译器
- GraalVM
- GraalVM虚拟机安装和体验
- GraalVM的下载和安装配置
- 安装Visual Studio
- GraalVM初体验
说明
- 本文章学习自Java新一代Graal编译器和GraalVM虚拟机
Java程序执行流程
JVM的语言无关性
JVM的执行流程
JVM(Java虚拟机)的执行流程包括类加载器子系统、运行时数据区和执行引擎三个主要组成部分。
-
类加载器子系统:类加载器子系统负责将字节码文件加载到内存中,并转换成可以被JVM执行的内部表示形式。它由三个主要的类加载器组成
- 启动类加载器(Bootstrap Class Loader):负责加载Java的核心库,如rt.jar等。
- 扩展类加载器(Extension Class Loader):加载Java的扩展库,如jre/lib/ext目录下的JAR文件。
- 应用程序类加载器(Application Class Loader):也称为系统类加载器,负责加载应用程序类路径上指定的类。
-
运行时数据区:运行时数据区是JVM用于执行程序时存储数据的区域,主要包括以下几个部分
- 方法区(Method Area):用于存储类的结构信息,如类的字段、方法、常量池等。
- 堆(Heap):用于存储创建的对象实例和数组。
- 栈(Stack):每个线程在执行过程中会创建一个栈帧,用于存储方法的局部变量、操作数栈、方法出口等信息。
- 本地方法栈(Native Method Stack):用于存储调用本地方法(Native Method)的栈。
-
执行引擎:执行引擎负责执行加载到内存中的字节码指令。它将字节码指令解释为具体的机器指令或直接通过即时编译技术将字节码编译成本地机器代码执行。执行引擎包括以下几个主要组件
- 解释器(Interpreter):逐行解释字节码指令并执行。
- 即时编译器(Just-In-Time Compiler,JIT):将热点代码(经常被执行的代码)编译成本地机器码执行,以提高执行速度。
- 垃圾收集器(Garbage Collector):负责自动回收堆中不再使用的对象。
- 通过类加载器子系统加载类文件,将类文件转换成运行时数据区的结构,然后由执行引擎执行相应的字节码指令,最终完成Java程序的执行过程。这个执行流程保证了Java程序在不同平台上的可移植性和跨平台性。
- 运行时数据区
- 执行引擎
public class Test{ public static void main(String[] args){ int a=138; int b=362; int c=a+b; } }
执行引擎的两种行为:解释执行和编译
-
解释器作用
- 真正意义上所承担的角色是一个运行时“翻译者”,将字节码文件中的内容“翻译”为对应平台的本地机器指令执行。由于解释器在设计和实现上非常简单,因此除Java语言之外,还有许多高级语言同样也是基于解释器执行的,比如Python、Ped、Ruby等。但是在今天,基于解释器执行已经沦落为低效的代名词,并且时常被一些c/c++程序员所调侃。
-
时(JIT-justin time)编译器作用
- 为了解决上述解释器低效的问题,JVM平台支持一种叫作即时编译的技术。即时编译的目的是避免函数被解释执行,而是将整个函数体编译成为机器码,并且将机器码做缓存,再次执行的时候直接执行机器码,这种方式可以使执行效率大幅度提升
-
解释器启动时间较短,时编译器启动时间较长
-
例如,JDK1.8
C:\Users\HP>java -version
java version "1.8.0_341"
Java(TM) SE Runtime Environment (build 1.8.0_341-b10)
Java HotSpot(TM) 64-Bit Server VM (build 25.341-b10, mixed mode)
热点代码和热点代码探测方式
热点代码
- 热点代码
- 根据代码被调用执行的频率而定决定是否需要启动JIT编译器将字节码直接编译为对应平台的本地机器指令。那些需要被编译为本地代码的字节码,称之为“热点代码”(一个被多次调用的方法,或者是一个方法体内部循环次数较多的循环体都可以被称之为“热点代码”)
- JIT编译器在运行时会针对那些频繁被调用的“热点代码”做出深度优化,将其直接编译为对应平台的本地机器指令,以此提升Java程序的执行性能。
热点代码探测方式
- 热点代码探测方式
- 采用基于计数器的热点探测,HotSpotVM将会为每一个方法都建立2个不同类型的计数器,分别为方法调用计数器(Invocation Counter)和回边计数器(BackEdge Counter)
- 方法调用计数器:用于统计方法的调用欧数
- 回边计数器:则用于统计循环体执行的语环次数
- 以方法调用计数器为案例(回边计数器类似):该计数器就用于统计方法被调用的次数,默认阈值在 client模式下是 1500次,在 server模式下是10000次。超过这个阀值,就会触发JIT编译。
- JDK1.8默认模式为server模式,默认阈值为10000次
C:\Users\HP>java -version java version "1.8.0_341" Java(TM) SE Runtime Environment (build 1.8.0_341-b10) Java HotSpot(TM) 64-Bit Server VM (build 25.341-b10, mixed mode)
热点代码探测方式流程
HotSpotVM内嵌两个JIT编译器
- 在HotSpot VM中内嵌有两个JIT编译器,分别为Client Compiler和Server Compiler,简称为C1编译器和C2编译器。
- c2编译器启动时长比c1编译器慢,但在系统稳定执行后,c2编译器执行速度远远快于c1编译器
Graal编译器
- 自JDK10后,Hotspot加入了全新的即时编译器:Graal编译器。编译效果追评C2编译器。Graal编译器是甲骨文实验室所做,能够替换c2的JIT编译器。
- Graal编译器和c2编译器的区别:
- C2编译器:C++所写
- Graal编译器:java所写、优化更激进、开发时间比较现代
GraalVM
- Graal编译器是GraalVM的核心组件,在HotSpot上装载Graal编译器,这上面还可以运行很多JVM 语言的,例如:Groovy、Java、Scala、Kotlin、Clojure。甲骨文实验室在此基础上,又开发了一个名为Trufle的框架,它是一个语言实现框架,可以让用户在这上面实现自己语言,目前可以实现并维护的语言:JS,Ruby,R,Python,C/C++、Fortran等。
GraalVM虚拟机安装和体验
GraalVM的下载和安装配置
- graalVM下载地址,选择合适的版本下载
- 解压下载文件,放到自定义目录
- 配置环境变量
JAVA_HOME: C:\Program Files\Java\graalvm-jdk-17.0.10+11.1 Path: %JAVA_HOME%\bin
- 验证安装成功
C:\Users\HP>java -version java version "17.0.10" 2024-01-16 LTS Java(TM) SE Runtime Environment Oracle GraalVM 17.0.10+11.1 (build 17.0.10+11-LTS-jvmci-23.0-b27) Java HotSpot(TM) 64-Bit Server VM Oracle GraalVM 17.0.10+11.1 (build 17.0.10+11-LTS-jvmci-23.0-b27, mixed mode, sharing)
- 安装native-image
- GraalVM中的native-image是一个工具,它可以将Java应用程序编译成本地可执行文件,而不需要JVM。这意味着应用程序可以更快地启动并且占用更少的内存,因为它们不再需要JVM来运行。
- native-image还可以提高应用程序的性能,因为它们可以直接在操作系统上运行,而不需要通过JVM进行解释。这使得GraalVM成为一个强大的工具,可以用于构建高性能的本地应用程序。
# gu 帮助命令
gu --help
# 查看已经安装的工具
gu list
# 如果没有自带,请执行安装命令,建议开启魔法
gu install native-image
C:\Users\HP>gu list
ComponentId Version Component name Stability Origin
---------------------------------------------------------------------------------------------------------------------------------
graalvm 23.0.3 GraalVM Core Supported
native-image 23.0.3 Native Image Early adopter
安装Visual Studio
-
安装Visual Studio编译为平台码所用
- 安装Visual Studio主要是GraalVM将class文件编译成exe文件需要MSVC环境,虽然体积很大,但安装简单
- 安装教程,参考网络即可
- 注意安装组件,如下
-
配置环境变量:请打开自己的机器目录进行查看
INCLUDE:
C:\Program Files (x86)\Windows Kits\10\Include\10.0.19041.0\ucrt
C:\Program Files (x86)\Windows Kits\10\Include\10.0.19041.0\um
C:\Program Files (x86)\Windows Kits\10\Include\10.0.19041.0\shared
C:\Program Files\Microsoft Visual Studio\2022\Community\VC\Tools\MSVC\14.38.33130\include
LIB:
C:\Program Files (x86)\Windows Kits\10\Lib\10.0.19041.0\um\x64
C:\Program Files (x86)\Windows Kits\10\Lib\10.0.19041.0\ucrt\x64
C:\Program Files\Microsoft Visual Studio\2022\Community\VC\Tools\MSVC\14.38.33130\lib\x64
PATH:
C:\Program Files\Microsoft Visual Studio\2022\Community\VC\Tools\MSVC\14.38.33130\bin\Hostx64\x64
GraalVM初体验
- 编写源文件
HelloWGraalVM.java
import java.util.Scanner; public class HelloWGraalVM { public static void main(String[] args) { System.out.println("hello GraalVM"); Scanner scanner = new Scanner(System.in); System.out.println("please input:"); String input = scanner.nextLine(); if ("-1".equals(input)) { System.out.println("exit"); } } }
- 编译成class文件
javac HelloWGraalVM.java
- 编译为本地可执行文件
- 使用native-image命令,需要先将Java源代码编译成class文件,然后再使用native-image进行编译
```bash
native-image HelloWGraalVM
```