1、JVM 是什么?
Java 虚拟机 (Java virtual machine,JVM)是 Java 程序运行基础,Java虚拟机有自己完善的硬件架构,如处理器、堆栈等,还具有相应的指令系统。
Java虚拟机本质上就是一个程序,当它在 命令行 上启动的时候,就开始执行保存在某字节码文件中的指令。Java语言的可移植性正是建立在Java虚拟机的基础上。任何平台只要装有针对于该平台的Java虚拟机,字节码文件(.class)就可以在该平台上运行。这就是“一次编译,多次运行”。
如上图所示,JVM 知识点有 6 个大方向,其中,内存模型、类加载机制、GC 垃圾回收是比较重点的内容。性能调优部分偏重实际应用,重点突出实践能力。编译器优化和执行模式部分偏重理论基础,作为java大佬可能要了解全部内容,作为 Android 仅仅了解内存模型、类加载机制、GC 垃圾回收这几项就可以了。
各个部分需要了解的知识点如下。
- 内存模型:程序计数器、方法区、堆、栈、本地方法栈的作用,保存哪些数据。
- 类加载:双亲委派的加载机制,以及常用类加载器分别加载哪种类型的类。
- GC:分代回收的思想和依据,以及不同垃圾回收算法实现的思路、适合的场景。
- 性能调优:常用的 JVM 优化参数的作用,参数调优的依据,常用的 JVM 分析工具能分析哪类问题,以及使用方法。
- 执行模式:解释、编译、混合模式的优缺点,Java7 提供的分层编译技术。需要知道 JIT 即时编译技术和 OSR(栈上替换),知道 C1、C2 编译器针对的场景,其中 C2 针对 Server 模式,优化更激进。在新技术方面可以了解 Java10 提供的由 Java 实现的 Graal 编译器。
- 编译优化:前端编译器 javac 的编译过程、AST 抽象语法树、编译期优化和运行期优化。编译优化的常用技术包括公共子表达式的消除、方法内联、逃逸分析、栈上分配、同步消除等。明白了这些才能写出对编译器友好的代码。
下面咱们通过各个方面来理解 JVM 的这些知识。
2、JVM 工作流程
我相信有些人跟我一样对内存的堆内存(heap)和栈内存(Stack)是怎么划分的不是很清楚,看完这块保你明白的彻彻底底。
Java 的内存区域划分实际上远比这复杂:Java 虚拟机在执行 Java 程序的过程中,会把它所管理的内存划分为不同的数据区域。下面这张图描述了一个 Scc.java 文件被 JVM 加载到内存中的过程:
Scc.java 文件首先需要经过编译器编译,生成 Scc.class 字节码 文件。
Java 程序中访问Scc这个类时,需要通过 ClassLoader(类加载器)将Scc.class 加载到 JVM 的内存中。
JVM 中的内存可以划分为若干个不同的数据区域,主要分为:程序计数器、虚拟机栈、本地方法栈、堆、方法区。