目录

  • 1 基本概念
  • 2 JVM 运行机制
  • 3 JVM 的组成
  • 4 垃圾回收与算法
  • 4.1 如何确定垃圾
  • 4.1.1 引用记数法
  • 4.1.2 可达性分析法
  • 4.2 垃圾回收算法
  • 4.2.1 标记清除算法
  • 4.2.2 复制算法
  • 4.2.3 标记整理算法
  • 4.2.4 分代收集算法
  • 5 垃圾收集器
  • 6 JVM 类加载机制
  • 6.1 类加载过程


声明:本文章内容部分摘自于《Offer来了:Java 面试核心知识点精讲(原理篇)》

1 基本概念

JVM(Java Virtual Machine)即 Java 虚拟机。JVM 的作用是运行 Java 字节码。JVM 运行在操作系统之上,JVM 会对不同的操作系统(例:Linux、Window、MacOS)做适配,这样我们开发 Java 代码的时候就无需关注各个底层操作系统的差异性,这也就是我们常说的 Java 伟大的跨平台特性。




应用代码

虚拟机

操作系统

2 JVM 运行机制

JVM 的生命周期和 Java 进程一致。也就是说,JVM 随着 Java 进程的开始而开始实例化,随着 Java 进程的退出或关闭而实例消亡。

Java 程序的运行过程如下:

  1. Java 源文件被编译器编译成字节码文件。
  2. JVM 将字节码解释成相应操作系统的机器码。
  3. 机器码调用相应操作系统的本地方法库去执行相应的方法。

编译

解释

机器码

字节码.class

源文件.java

3 JVM 的组成

JVM 包括一个类加载器子系统、运行时数据区、执行引擎和本地接口库。本地接口库通过调用本地方法库与操作系统交互。它们各自的作用如下:

  • 类加载器子系统:将编译好的 .class 文件加载到 JVM 中;
  • 运行时数据区:存储 JVM 运行过程中产生的数据,包括程序计数器、方法区、本地方法区、虚拟机栈、虚拟机堆;
  • 执行引擎:即时编译器用于将 Java 字节码编译成具体的机器码;垃圾回收器用于回收在运行过程中不再使用的对象;
  • 本地接口库:调用操作系统的本地方法库完成具体的指令操作。

4 垃圾回收与算法

4.1 如何确定垃圾

Java 采用可达性分析法引用记数法来确定对象是否应该被回收。

4.1.1 引用记数法

在 Java 中如果要操作对象就必须先获得该对象的引用,因此可以通过引用记数法来判定一个对象是否可以被回收。在为对象添加一个引用时,引用计数 +1;在为对象删除一个引用时,引用计数 -1;如果一个对象的引用计数为 0,则表示此刻该对象没有被引用,是可以被回收的。

该方法的缺点是:有循环引用问题。循环引用即两个对象互相引用,导致它们的引用一直存在,无法被回收。

JAVA里jvm理解 jvm简单理解_JVM

4.1.2 可达性分析法

为了解决引用记数法的循环引用问题,Java 还采用了可达性分析法来判断对象是否可以被回收。具体做法是首先定义一些 GCRoots 对象,以 GCRoots 为起点向下搜索。如果从 GCRoots 到对象之间没有可达路径,那么说明该对象是不可达的。不可达对象要经过至少两次标记才能判定其是否可以被回收,如果在两次标记后该对象仍然是不可达的,那么该对象将被垃圾收集器回收。

4.2 垃圾回收算法

Java 中常用的垃圾回收算法有:标记清除、复制、标记整理、分代收集这 4 种垃圾回收算法。

JAVA里jvm理解 jvm简单理解_java_02

4.2.1 标记清除算法

标记清除算法是基础的垃圾回收算法。该算法过程分为两部分:标记和清除。首先在标记阶段标记出所有需要回收的对象,然后在清除阶段清除可回收的对象并释放其所占用的内存空间。

JAVA里jvm理解 jvm简单理解_开发语言_03


缺点:如果内存中可被回收的小对象居多,则会引起内存碎片化的问题,继而引起大对象无法获得连续可用空间的问题。

4.2.2 复制算法

为了解决标记清除法带来的内存碎片化问题,JVM 引入了复制算法。复制算法首先将内存划分为两块大小相等的内存区域,即区域1和区域2。新生成的对象都放在区域1中,区域1满后会对区域1进行1次标记,并将标记后存活的对象全部复制到区域2中,这时区域1内将不存在任何存活的对象,直接清理整个区域1即可。

优点:内存清理效率高且易于实现。

缺点:同一时刻只有一个内存区域可用,内存空间被压缩到原来的一半,因此存在大量的内存浪费。同时,在系统中有大量长时间存活的对象时,这些对象将在区域1和区域2之间来回复制而影响系统的运行效率。因此,该算法只在对象为『朝生夕死』状态时运行效率较高。

JAVA里jvm理解 jvm简单理解_java_04

4.2.3 标记整理算法

标记整理算法结合了标记清除算法和复制算法的优点。该算法过程分为两部分:标记和整理。首先在标记阶段标记出所有需要回收的对象,然后将存活的对象移动到内存的另一端,然后清除该端的对象并释放内存。

JAVA里jvm理解 jvm简单理解_java_05

4.2.4 分代收集算法

Java 对象有不同的类型,例如:长生命周期、短生命周期、大对象、小对象等。JVM 针对不同的对象类型采用不同的垃圾回收算法,这被称之为是分代收集算法
分代收集算法根据对象的不同类型将内存划分为不同的区域,JVM 将堆划分为新生代和老年代。由于不同区域有不同的对象特性,因此JVM 根据不同的区域选择了不同的垃圾回收算法。

  • 新生代:主要存放新生成的对象,其特点是对象数量多但生命周期短。在每次垃圾回收的时候都有大量的对象被回收。大部分 JVM 在该区域都采用了复制算法
  • 老年代:主要存放大对象和生命周期长的对象。此区域可回收的对象数量相对较少。该区域主要采用标记清除算法
  • 永久代:用于存储 Class 类、常量、方法描述等。在永久代主要回收废弃的常量和无用的类。
  • JAVA里jvm理解 jvm简单理解_java_06


5 垃圾收集器

JVM 针对新生代和老年代提供了多种不同的垃圾收集器。针对新生代的垃圾收集器有:Serial、ParNew、Parallel Scavenge;针对老年代的垃圾收集器有:CMS、Serial Old、Parallel Old;还有针对不同区域的 G1 分区收集算法。

JAVA里jvm理解 jvm简单理解_JAVA里jvm理解_07

6 JVM 类加载机制

6.1 类加载过程

JVM 的类加载分五个阶段:加载、连接、初始化、使用、卸载。

JAVA里jvm理解 jvm简单理解_开发语言_08

  1. 加载
    指 JVM 读取 Class 文件,并根据 Class 文件描述创建 java.lang.Class 对象的过程。即通过 findClass 找到 .class 文件并把这个文件包含的字节码加载到内存中。
  2. 验证
    字节码验证。主要用于确保 Class 文件符合当前虚拟机的要求,保障虚拟机自身的安全。
  3. 准备
    Class 类数据结构分析及相应的内存分配。主要工作是在方法区中为类变量分配内存空间并设置类中变量的初始值。
  4. 解析
    JVM 会将常量池中的符号引用替换为直接引用。
  5. 初始化
    主要通过执行类构造器的方法为类进行初始化,包括类中静态属性和初始化复制,以及静态块的执行等。