👋探索JVM架构
⚽️什么是Hotspot?
比较流行的JVM虚拟机包括HotSpot
、OpenJ9和GraalVM。
众所周知,Hotspot是最为广泛使用的JVM虚拟机,它是Oracle JDK和Open JDK默认的JVM实现,是一个用于桌面和服务器计算机的Java 虚拟机,由 Sun Microsystems, Inc 开发,现在由 Oracle, Inc. 维护和分发。它通过即时编译和自适应优化等方法提高了性能。
⚽️Hotspot的特性
- 动态编译和优化:HotSpot虚拟机会动态地将程序中频繁执行的热点代码编译成本地机器码,同时对编译后的机器码进行优化,以提高程序的运行效率。
- 即时编译:HotSpot虚拟机使用
即时编译
(Just-In-Time Compilation)技术,将字节码实时编译成本地机器码,从而减少了解释执行的开销。 - 垃圾收集:HotSpot虚拟机使用了成熟的垃圾收集算法和技术,例如
分代垃圾收集
、并发垃圾收集
等,以提高内存管理的效率。 - 高性能:HotSpot虚拟机通过运用编译和优化技术,以及垃圾收集算法的改进,实现了较高的执行性能,使得Java程序能够与传统编译语言的性能相媲美。
- 可移植性和兼容性:HotSpot虚拟机符合
Java虚拟机规范
,因此可以良好地支持Java应用程序的运行,保证了程序的可移植性和兼容性。 - 总的来说,HotSpot虚拟机通过动态编译和优化、即时编译、高效的垃圾收集等特性,提供了高性能和可移植性的Java运行环境。
⚽️Hotspot 架构
HotSpot JVM 拥有一个支持强大的特性和功能基础的架构,并支持实现高性能和大规模可扩展性的能力。例如,HotSpot JVM JIT 编译器会生成动态优化。换句话说,它们在 Java 应用程序运行时做出优化决策,并生成针对底层系统架构的高性能本机机器指令。此外,通过其运行时环境和多线程垃圾收集器的成熟发展和持续工程,HotSpot JVM 即使在最大的可用计算机系统上也能产生高可扩展性。
JVM 的主要组件包括:
类加载器子系统
:负责加载、链接和初始化Java类文件(即“Java文件”),也称为动态类加载,用于将类加载到内存中并使其可供执行。运行时数据区
:内存区域的划分,包含方法区、PC 寄存器、堆栈区和线程。执行引擎
:包含解释器、编译器和垃圾收集器。
⚽️类加载器子系统
⚾️加载器的分类
- 启动类加载器(Bootstrap ClassLoader):这个类加载器使用c/c++语言实现的,嵌套在JVM内部,就是JVM的一部分。它用来加载Java的核心库(JAVA_HOME/jre/lib/rt.jar or resources.jar或sun.boot.class.path路径下的内容),用于提供JVM自身需要的类,并不继承java.lang.ClassLoader,没有父加载器。
- 扩展类加载器(Extension ClassLoader):该类加载器用来加载扩展类和应用程序类加载器,并指定为他们的父类加载器。
- 应用程序类加载器(Application ClassLoader):该类加载器负责加载应用程序中的类。
⚾️类加载器子系统的工作原理
- 当Java程序启动时,JVM会使用启动类加载器加载核心类库,这些类库位于JVM的lib目录中,如rt.jar、resources.jar等。这些类库包含了Java虚拟机的运行所必需的类和资源。
- 当Java程序需要加载其他类时,会通过其他类加载器来完成。这些类加载器通过继承ClassLoader类,实现了加载、链接和初始化类的功能。根据引用的内容,除了启动类加载器,其他类加载器都继承自ClassLoader类。
- 类加载器采用双亲委派模型来加载类。即当类加载器收到类加载请求时,它会先将请求传递给其父类加载器,如果父类加载器能够加载成功,则直接返回已加载的类;如果父类加载器无法加载,则子类加载器才会尝试加载类。这样可以确保类加载的一致性和安全性。
- 类加载器在加载类时会经过加载、链接和初始化三个阶段。加载阶段将类的字节码从文件中读取到内存中;链接阶段将类与其它类关联起来,并进行一些校验工作;初始化阶段则是对类进行初始化,包括执行静态代码块和初始化静态变量等。
总结起来,JVM的类加载器子系统负责将Java类加载到内存中,并按照一定的加载顺序进行加载和初始化。通过双亲委派模型,它能够保证类的一致性和安全性。启动类加载器负责加载核心类库,而其他类加载器负责加载应用程序所需的类。这样可以实现类的动态加载和模块化开发。
⚽️运行时数据区
JVM运行时数据区是Java虚拟机在运行过程中用来存储和管理数据的区域。根据引用提供的信息,Java虚拟机的运行时数据区包括以下几个部分:
程序计数器
(Program Counter Register):用于记录当前线程执行的字节码指令地址。每个线程都有自己独立的程序计数器。Java栈
(Java Stack):每个线程在执行Java方法时会创建一个对应的栈帧。栈帧包含局部变量表、操作数栈、动态链接、方法出口等信息。引用没有具体提及Java栈,但根据通常的Java虚拟机实现,Java栈通常与方法区是相互关联的。本地方法栈
(Native Method Stack):用于执行本地方法的栈。本地方法栈也类似于Java栈,但是用于执行本地方法(即使用本地语言如C/C++实现的方法)。堆(Heap)
:用于存储对象实例和数组的区域。堆是Java虚拟机管理的最大的一块内存区域,也是Java程序运行时的主要内存区域。方法区(Method Area)
:用于存储类的结构信息,如类的字段、方法、常量池、静态变量等。引用提到了方法区,它是Java虚拟机的一部分,一般是独立于堆的内存空间。
综上所述,JVM的运行时数据区包括程序计数器、Java栈、本地方法栈、堆和方法区。这些区域各自承担着不同的功能和存储任务,共同支持Java程序的运行。
⚽️执行引擎
JVM的执行引擎主要负责以下任务:
加载
:加载是指将Java字节码文件(.class文件)从文件系统或网络中加载到JVM中。加载过程包括验证、准备和解析三个阶段。验证阶段会确保加载的字节码是正确的,准备阶段会为静态变量分配内存并初始化为默认值,解析阶段会把类、接口、字段和方法的符号引用解析为直接引用。链接
:链接包含验证、准备和解析三个阶段。验证阶段会检查类型转换、方法调用和方法返回等操作的正确性。准备阶段会为类型变量进行类型推断赋值,解析阶段会将常量池中的符号引用解析为直接引用。初始化
:初始化阶段会执行类构造器方法(()方法)。这个方法是由编译器自动收集类中的所有类变量的赋值动作和静态代码块集合来的。执行
:在JVM执行引擎中,执行是通过解释和编译两种方式进行的。解释方式是按字节码逐条解释执行的,编译方式是将字节码转化为本地机器代码再执行。垃圾回收
:JVM的内存管理包括堆内存、栈内存和方法区等,JVM需要回收不再使用的对象占用的内存空间,这就是垃圾回收。垃圾回收是自动进行的,有两种主要方式:标记-清除(Mark-Sweep)和复制(Copying)。
以上是JVM执行引擎的基本概述,具体的实现方式和行为可能会根据JVM的实现和版本有所不同。