原创

JVM框架

备注:本章虽然放到了 JVM 的第一章,但是不建议优先先阅读,可以先大概浏览,如果想认真品味,建议放到 JVM 知识体系最后一篇来阅读,在有了一些知识储备之后,才能更好的理解整体架构,才能更好的明白我们 JVM 到底是怎么工作的。

1.什么是 JVM

Java 虚拟机有自己完善的硬件架构,如处理器、堆栈等,还具有相应的指令系统。 Java 虚拟机本质上就是一个程序, 当它在命令行上启动的时候,就开始执行保存在某字节码文件中的指令。Java 语言的可移植性正是建立在 Java 虚拟机的基础上。任何平台只要装有针对于该平台的 Java 虚拟机,字节码文件(.class)就可以在该平台上运行。这就是“ 一次编译,多次运行 ”。

既然 JVM 是一个程序,看一下 JVM 架构图

JVM架构图
JVM架构图

2.JVM 分层

做架构的都很清楚,一个复杂的系统,我们可以按照需求给他分层,分模块,解耦之后就很容易实现了,从上图,我们可以看到 JVM 设计团队将其拆分为三个子系统:

  • 类加载系统

  • 运行时数据区

  • 执行引擎

类加载系统

java 的动态类加载功能在类加载子系统中实现。当第一次在运行时(不是在编译时)涉及到一个 class 时,它会加载,链接并初始化类文件。

加载:类会通过这个组件加载。根加载器(rt.jar),扩展加载器(jrelibext)和系统加载器(classpath 下的)是其主要的工具。

链接:主要分层三步

检查:判断其字节码是否符合虚拟器要求

准备:分配静态变量的空间,同时赋缺省值

解析:解析符号链接,链接到方法区的引用上去

初始化:给静态变量赋初值,并执行静态代码区

运行时数据区

运行时数据区分成 5 个组件 方法区:保存所有类数据,包括静态变量。一个 jvm 对应一个方法区。

:保存所有的对象,对象中的变量以及数组。一个 jvm 对应一个堆。因为多个线程共享一个方法区和堆,所以数据保存不是线程安全的。

:每一个线程都会创建一个运行时的栈。对于每一个方法调用,都会在栈中创建一个栈帧。栈中保存了所有的本地变量。栈是线程安全的,因为它是线程独享资源。

PC 寄存器:每个线程有一个 PC 寄存器,用来记录当前执行指令的地址,当一条指令执行完毕,它就会指向下一条指令。

本地方法栈:保存了本地方法的信息,每个线程会创建自己的本地方法栈。

执行引擎

分配给运行时数据区的字节码将由执行引擎执行,执行引擎读取字节码并逐个执行。

解释器:解释器更快地解释字节码,但执行缓慢。解释器的缺点是当一个方法被调用多次时,每次都需要一个新的解释;

JIT 编译器:JIT 编译器消除了解释器的缺点。执行引擎将在转换字节码时使用解释器的帮助,但是当它发现重复的代码时,将使用 JIT 编译器,它编译整个字节码并将其更改为本地代码。通常一段代码需要执行多少次才会触发 JIT 优化呢?通常这个值由-XX:CompileThreshold 参数进行设置:使用 client 编译器时,默认为 1500;使用 server 编译器时,默认为 10000;这个本地代码将直接用于重复的方法调用,这提高了系统的性能。

JIT 的构成组件为:

  • 中间代码生成器(Intermediate Code Generator):生成中间代码
  • 代码优化器(Code Optimizer):负责优化上面生成的中间代码
  • 目标代码生成器(Target Code Generator):负责生成机器代码或本地代码
  • 分析器(Profiler):一个特殊组件,负责查找热点,即该方法是否被多次调用;
  • 垃圾收集器(Garbage Collector):收集和删除未引用的对象。可以通过调用“System.gc()”触发垃圾收集,但不能保证执行。JVM 的垃圾回收对象是已创建的对象。
  • Java 本机接口(JNI):JNI 将与本机方法库进行交互,并提供执行引擎所需的本机库。
  • 本地方法库(Native Method Libraries):它是执行引擎所需的本机库的集合。
正文到此结束