Java 虚拟机 ( 简读版 )

382 阅读4分钟

1. 背景

本文聊聊Java 虚拟机的一些知识。

2.知识

Java Virtual Machine(Java虚拟机,简称JVM)是一个抽象的计算机器。像真正的计算机器一样,它有一个指令集并在运行时操纵各种内存区域。

拆分几个过程来理解概貌

JVM 使得 Java程序 与 操作系统(及硬件)保持独立性。JVM 并不依赖 Java 编程语言 ,它只知道一种特定的二进制格式,即class文件格式。一个class文件包含着Java虚拟机指令(或字节码)和符号表,以及其它辅助信息。

拆分几个过程来理解:

  • 1、Java 语言写的 Java 文件,比如 xxx.java 文件 经过编译后 变成 class 文件格式的 “字节码” 文件。
  • 2、字节码文件经过压缩后被打包成一个 jar 文件。
  • 3、Jar 文件可被分发到 安装了JVM的 Windows 或者 Linux 的计算机上,Jar包内的 class字节码 被传入 JVM 。JVM负责 将 字节码 解释成具体的机器指令来执行。

JVM 具体可以由 ”JVM 规范“ 定义,有很多厂商提供了JVM的实现。比如:Oracle 的 JVM 之一名为 HotSpot,另一个继承自BEA Systems 的是JRockit。Android 使用了 Dalvik虚拟机,ART虚拟机。

3. JVM 核心组成部分(三大项)

也就是说 JVM 有这些组成部分:

  • 1、它有指令集 (即:字节码 )
  • 2、它有 指令解释器 来 解析指令。 (即:字节码执行器和JIT)
  • 3、它可以操作 内存区域,以装载和执行。(即:操作内存 )

重点这三项,我们慢慢讲。

3.1、字节码指令

JVM 具有针对以下任务组的字节码指令规范:

  • 加载和存储
  • 算术
  • 类型转换
  • 对象创建和操作
  • 操作数栈管理(push/pop)
  • 控制转移(分支)
  • 方法调用和返回
  • 抛出异常
  • 基于监视器的并发

这些指令是一些操作任务,被加载到JVM后可以被执行。

3.2、字节码解释器和即时编译器

(1) 字节码解释器 ( bytecode interpreter ) 字节码解释器用于将字节码解析成计算机能执行的语言,一台计算机有了 Java 字节码解释器后,它就可以运行任何 Java 字节码程序。同样的 Java 程序就可以在具有了这种解释器的硬件架构的计算机上运行,实现了“跨平台”。

(2) 即时编译器 ( just-in-time compiler,JIT ) JIT 编译器可以在执行程序时将 Java 字节码翻译成本地机器语言

一般来讲,Java 字节码经过 字节码解释器执行时,执行速度总是比编译成本地机器语言的同一程序的执行速度慢。而 即时编译器 在执行程序时将 Java 字节码翻译成本地机器语言,以显著加快整体执行时间。

3.3、虚拟机架构

JVM 操作内存有这些:

  • JVM 有一个堆( heap )用于存储对象和数组。垃圾回收器要在这里工作。

  • 代码、常量和其他类数据存储在方法区( method area )中。

  • 每个 JVM 线程也有自己的调用栈( JVM stack ),用于存储 “帧”。每次调用方法时都会创建一个新的 帧(放到栈里),并在该方法退出时销毁该帧。

  • 每个提供一个操作数堆栈 ( operand stack) 和一个局部变量数组 ( local variables ) 。操作数栈用于计算操作数和接收被调用方法的 "返回值",而局部变量数据用于传递“方法参数”。

为了兼容性。每个特定的主机操作系统都需要自己的 JVM 和运行时实现。虽然实际实现可能不同,但是 在语义上都以相同的方式解释字节码。

还与重要的垃圾回收机制,我们后面再讲。

3.4 类加载器 ( Class loader )

JVM 字节码的基本单位是。类加载器 ( Class loader ) 用于识别和加载符合 Java的 Class 文件格式的内容。

类加载器按顺序执行下面三个活动:

  • 1)加载( Loading ):查找和导入二进制数据内容
  • 2)链接( Linking ):执行下面三个子步骤 -- 2.1) 验证(Verification):确保导入内容的正确性 -- 2.2 )准备(Preparation):为类变量分配内存,并将内存初始化为默认值 -- 2.3) 解析(Resolution):将符号引用(symbolic references)转换为直接引用(direct references)。
  • 3)初始化( Initialization ):调用Java 代码 ,将类变量初始化为其正确起始值 。

一般来说,有两种类型的类加载器:

  • 1、引导类加载器
  • 2、用户定义的类加载器。

每个 Java 虚拟机实现都必须有一个引导类加载器 ( bootstrap class loader ),能够加载受信任的类,以及一个扩展类加载器或应用程序类加载器 ( application class loader)。

3.5 JVM 语言

有很多种 JVM 语言可以选择,比如 Groovy、Scala和 Kotlin 等,这些语言编写的代码都可以被编译成 字节码后 在JVM 上运行。

4. 垃圾回收器( GC )

...

5.参考:

Oracle 的 Java 虚拟机规范 docs.oracle.com/javase/spec… 维基百科 en.m.wikipedia.org/wiki/Java_v…