JVM 可达性分析法1. 前言上节课我们结束了运行时数据区的讲解,本节课程开始,我们来对执行引擎进行讲解,在执行引擎模块中,首当其冲的就是垃圾回收器。本节主要知识点如下:
2. 垃圾回收器的位置我们在 JVM 整体架构介绍的小节提到过 JVM 的垃圾回收器位于执行引擎中。而当时我们的执行引擎只是简单的画了下,那么我们先来看下执行引擎的更细致的结构如下图:
3. 垃圾回收器的基本概念什么是垃圾回收器:JVM 为 Java 提供了垃圾回收机制,其实是一种偏自动的内存管理机制。简单来说,垃圾回收器会自动追踪所有正在使用的对象,并将其余未被使用的对象标记为垃圾,不需要开发者手动进行垃圾回收,JVM 自动进行垃圾回收,释放内容。 为什么进行垃圾回收:如果不进行垃圾回收,内存迟早都会被消耗空,因为我们在不断的分配内存空间而不进行回收。除非内存无限大,我们可以任性的分配不回收,但是事实并非如此。所以,垃圾回收是必须的。 哪些内存需要回收:哪些内存需要回收是垃圾回收机制第一个要考虑的问题,所谓“要回收的垃圾”无非就是那些不可能再被任何途径所使用的对象。无需再使用的对象,会被标记为垃圾,等待JVM回收此部分内存。
4. 可达性分析法基本原理方法原理:通过一系列称为"GC Roots"的对象作为起始点,从这些节点向下搜索,搜索所走过的路径称为引用链(即GC Roots到对象不可达时),则证明此对象是不可用的。 那么问题又来了,如何选取 GCRoots 对象呢?在 Java 语言中,可以作为 GCRoots 的对象包括下面几种:
Tips:看了如上的原理与 GC Roots 选择的描述,感觉概念性问题比较抽象,难于理解,我们继续通过示例来进一步理解可达性分析法。 4. 可达性分析法示例上文中提到了,可达性分析法是通过 GC Roots 为起点的搜索,有四种对象可以作为 GC Roots,那么我们通过如下示意图来理解下,何为不可达对象。 GC Roots 四种类型解释:从上图中,我们可以看到四种 GC Roots。这里我们对这四种 GC Roots 做一下更为细致的解释。
从上图来理解可达性分析法就会非常简单,四种 GC Roots 无非是 Java 中的引用对象,从GC Roots 出发,类似于我们使用开发工具看代码,发现某部分代码用不到了,我们就会删除这部分代码。其实可达性分析法也是如此,发现某些对象不可达了,就会被垃圾回收器收集。 从上图中来看,对象 A,B,C,D,E,F 为可达对象;而对象 G,H,I,J,K 为不可达对象,会被标记为垃圾对象,最终被垃圾回收器回收。 5. 小结本节讲解了垃圾回收回收器的定义以及垃圾回收器存在的意义,并在此基础上讲解了垃圾回收器是如何判定对象的可达性的。可达性分析法是本节的核心知识点,是必须要掌握的知识点。 在讲解 GC Roots 的知识点时,我们总是会使用 “引用对象” 这四个字,其中引用又分为 4 种引用,下节课程我们会详细的讲解。 JVM 四种引用1. 前言延续上节可达性分析法的讲解,本节主要讲解可达性分析法所使用的四种引用类型,本节主要内容如下:
2. 可达性分析的四种引用类型上节课程内容讲解了可达性分析,可达性分析的 GC Roots 均为引用对象,那么引用对象有 4 种引用类型如下:
本节课程内容与可达性分析相辅相成,学习者务必在学习完可达性分析内容后再学习本节内容。 3. 强引用定义:强引用就是指在程序代码之中普遍存在的,类似 代码示例:
在强引用的定义中有这样一句话:“只要强引用还存在,垃圾收集器永远不会回收掉被引用的对象。” 那么有没有办法将强引用消除呢? 消除强引用示例代码:
如果不使用强引用时,可以赋值 4. 软引用定义:软引用用来描述一些还有用,但并非必需的对象。对于软引用关联着的对象,如果内存充足,则垃圾回收器不会回收该对象,如果内存不够了,就会回收这些对象的内存。 在 JDK 1.2 之后,提供了 SoftReference 类来实现软引用。软引用可用来实现内存敏感的高速缓存。软引用可以和一个引用队列(ReferenceQueue)联合使用,如果软引用所引用的对象被垃圾回收器回收,Java虚拟机就会把这个软引用加入到与之关联的引用队列中。 软引用使用场景:Android 应用图片 但是,由于图片占用内存空间比较大,缓存很多图片需要很多的内存,就可能比较容易发生 OutOfMemory 异常。这时,我们可以考虑使用软引用技术来避免这个问题发生。 SoftReference 可以解决 OOM 的问题,每一个对象通过软引用进行实例化,这个对象就以cache的形式保存起来,当再次调用这个对象时,那么直接通过软引用中的 get() 方法,就可以得到对象中的资源数据,这样就没必要再次进行读取了,直接从 cache 中就可以读取得到,当内存将要发生 OOM 的时候,GC 会迅速把所有的软引用清除,防止 OOM 发生。 5. 弱引用定义:弱引用描述非必需对象。被弱引用关联的对象只能生存到下一次垃圾回收之前,垃圾收集器工作之后,无论当前内存是否足够,都会回收掉只被弱引用关联的对象。Java 中的类 WeakReference 表示弱引用。 代码示例:
结果验证:第二个输出结果是 null,这说明只要 JVM 进行垃圾回收,被弱引用关联的对象必定会被回收掉。
6. 虚引用定义:"虚引用"顾名思义,就是形同虚设,与其他几种引用都不同,虚引用并不会决定对象的生命周期。如果一个对象仅持有虚引用,那么它就和没有任何引用一样,在任何时候都可能被垃圾回收。虚引用在 Java 中使用 作用:虚引用主要用来跟踪对象被垃圾回收的活动。 虚引用与软引用和弱引用的区别:虚引用必须和引用队列(ReferenceQueue)联合使用。当垃圾回收器准备回收一个对象时,如果发现它还有虚引用,就会在回收对象的内存之前,把这个虚引用加入到与之关联的引用队列中。程序可以通过判断引用队列中是否已经加入了虚引用,来了解被引用的对象是否将要被垃圾回收。程序如果发现某个虚引用已经被加入到引用队列,那么就可以在所引用的对象的内存被回收之前采取必要的行动。 使用示例:虚引用必须和引用队列(ReferenceQueue)联合使用
7. 小结本节主要讲解可达性分析的四种对象引用类型,通篇皆为重点内容,需要学习者理解并掌握这四种引用类型。 JVM 常见的垃圾回收算法1. 前言本节主要讲解垃圾回收算法,并对每一种算法进行讲解。垃圾回收算法在垃圾回收器中占据着十分重要的地位,对本节内容一定要格外重视。本节主要内容如下:
通篇皆为重点内容,务必要用心学习。 2. 垃圾回收算法种类我们先来讨论一个问题,垃圾回收算法有几种? 如果单纯从一些博客或者论坛上的内容来说,部分作者会将垃圾回收分为如下 4 种算法:
但是这种分类是不准确的,准确来说,垃圾回收只有 3 种算法:
为什么会有所谓的“分代收集算法”呢? 此处我们埋下一个伏笔,后文中我会在适当的地方给予解释。 3. 标记-清除(Mark-Sweep)算法标记 - 清除(Mark-Sweep)算法是最基本的算法。 基本概念:标记-清除算法就如同它的名字一样,分为“标记”和“清除”两个阶段:
缺点:这种算法的不足主要体现在效率和空间。
为了更加透彻的理解标记-清除(Mark-Sweep)算法,我们来看下如下示意图,通过直观的图形展示,彻底搞懂标记-清除(Mark-Sweep)算法。 4. 复制(coping)算法
基本概念:复制算法是为了解决效率问题而出现的,它将可用的内存分为两块,每次只用其中的一块,当这一块内存用完了,就将还存活着的对象复制到另外一块上面,然后再把已经使用过的内存一次性清理掉。这样每次只需要对整个半区进行内存回收,内存分配的执行过程如下图所示: 缺点:不过这种算法有个缺点,内存缩小为原来的一半,这样代价太高了。 现在的商用模拟机都采用这种算法来回收新生代,不过研究表明1:1的比例非常不科学,因此新生代的内存被划分为一块较大的Eden空间和两块较小的Survivor空间,每次使用Eden和其中一块Survivor。 每次回收时,将Eden和Survivor中还存活着的对象一次性复制到另外一块Survivor空间上,最后清理掉Eden和刚才使用过的Survivor空间。 HotSpot虚拟机默认Eden区和Survivor区的比例为8:1,意思是每次新生代中可用内存空间为整个新生代容量的90%。当然,我们没有办法保证每次回收都只有不多于10%的对象存活,当Survivor空间不够用时,需要依赖老年代进行分配担保(Handle Promotion)。 5. 标记-整理(Mark-Compact)算法
根据老年代的特点,有人提出了另外标记-整理(Mark-Compact)算法,标记过程与标记-整理(Mark-Compact)算法一样,不过不是直接对可回收对象进行整理,而是让所有存活对象都向一端移动,然后清理掉边界以外的内存。标记-整理算法的工作过程如图: 6. 分代清理问题:我们上文埋下了伏笔,分代清理到底是不是第四种算法呢? 解答:不是,我们通常称之为分代收集理论,或称之为分代收集思想。目前虚拟机基本都采用分代收集理论来进行垃圾回收。 分代收集理论结合了以上的 3 种算法,根据对象的生命周期的不同将内存划分为几块,然后根据各块的特点采用最适当的收集算法。准确的说,分代收集理论就是在不同的内存区域使用不同的算法,它是 以上 3 种算法的使用者。 因此说,分代清理并非是一种单独的算法,而是一种收集理论。 7. 小结本节内容主要讲解了垃圾回收的 3 种算法和分代收集理论。通篇皆为重点掌握内容,是垃圾回收的核心知识点。学习者可以结合给出的示意图进行理解,这样能够更好地掌握本节所讲的内容。 JVM 垃圾回收器分类1. 前言本节主要讲解 7 种垃圾回收器,其中有 3 种垃圾回收器是作用于年轻代垃圾回收的收集器;另外 3 种圾回收器是作用于老年代垃圾回收的收集器;剩余的 1 种垃圾回收器能够同时作用于年轻代和老年代。 7 种垃圾回收器以及其作用的内存区域如下图所示: 通篇皆为重点知识,请认真学习并理解每种垃圾回收器的特点。 2. Serial收集器基本概念:Serial收集器是最基本、发展历史最久的收集器,这个收集器是采用复制算法的单线程的收集器。
单线程的收集器:单线程一方面意味着他只会使用一个 CPU 或者一条线程去完成垃圾收集工作,另一方面也意味着他进行垃圾收集时必须暂停其他线程的所有工作,直到它收集结束为止。 不过实际上到目前为止,Serial收集器依然是虚拟机运行在 Client 模式下的默认新生代收集器,因为它简单而高效。Serial 收集器运行过程如下图所示: 3. Parnew收集器基本概念:Parnew 收集器其实就是Serial收集器的多线程版本,除了使用多线程进行垃圾收集外,其余行为和 Serial 收集器完全一样,但是他却是 Server 模式下的虚拟机首选的新生代收集器。
特点:
Parnew 收集器运行过程如图所示: 4. Parallel Scavenge收集器基本概念:Parallel Scavenge 收集器也是一个新生代收集器,也采用了复制算法,也是并行的多线程收集器。Parallel Scavenge 收集器的目标是达到一个可控制的吞吐量。Parallel Scavenge 收集器是虚拟机运行在 Server 模式下的默认垃圾收集器。被称为“吞吐量优先收集器”。
Parallel Scavenge 收集器运行过程同 Parnew 收集器一样: 控制吞吐量:CMS 等收集器的关注点是尽可能缩短垃圾收集时用户线程的停顿时间,而 Parallel Scavenge 收集器的目标则是达到一个可控制的吞吐量。所谓吞吐量就是 CPU 用于运行用户代码时间与 CPU 总消耗时间的比值,即 空间吞吐量参数介绍:虚拟机提供了 Parallel Scavenge 收集器有一个参数 -XX:UseAdaptiveSizePolicy 参数,这是一个开关参数,这个参数打开之后,就不需要手动指定新生代大小、Eden 区和 Survivor 参数等细节参数了,虚拟机会根据当前系统的运行情况以及性能监控信息,动态调整这些参数以提供最合适的停顿时间或者最大的吞吐量。 如果对于垃圾收集器运作原理不太了解,以至于在优化比较困难的时候,可以使用 Parallel Scavenge收集器配合自适应调节策略,把内存管理的调优任务交给虚拟机去完成。 5. Serial Old收集器基本概念:Serial Old 收集器同样是一个单线程收集器,作用于老年代,使用“标记-整理算法”,这个收集器的主要意义也是在于给 Client 模式下的虚拟机使用。 Serial Old 收集器运行过程如图所示: 6. Parallel Old收集器基本概念:Parallel Old 收集器是 Parallel Scavenge 收集器的老年代版本,使用多线程和“标记-整理算法”进行垃圾回收。 这个收集器在 JDK 1.6 之后的出现,“吞吐量优先收集器”终于有了比较名副其实的应用组合,在注重吞吐量以及 CPU 资源敏感的场合,都可以优先考虑
7. CMS收集器基本概念:CMS(Conrrurent Mark Sweep,连续标记扫描)收集器是以获取最短回收停顿时间为目标的收集器。使用标记-清除算法。 收集步骤:收集过程分为如下四步:
CMS 收集器运行过程如下图所示: 8. G1收集器基本概念:G1 是目前技术发展的最前沿成果之一,HotSpot开发团队赋予它的使命是未来可以替换掉 JDK1.5 中发布的 CMS 收集器。 与其他GC收集器相比,G1收集器具有以下特点:
在G1之前的垃圾收集器,收集的范围都是整个新生代或者老年代,而 G1 不再是这样。使用 G1 收集器时,Java 堆的内存布局与其他收集器有很大差别,它将整个Java堆划分为多个大小相等的独立区域(Region),虽然还保留有新生代和老年代的概念,但新生代和老年代不再是物理隔离的了,它们都是一部分(可以不连续)Region 的集合。 9. 小结本节主要讲解了 7 种垃圾收集器:Serial 收集器,Parnew 收集器,Parallel Scavenge 收集器,Serial Old 收集器,Parallel Old 收集器,CMS 收集器和G1 收集器。 其中专门针对年轻代的收集器有 Serial 收集器,Parnew 收集器和 Parallel Scavenge 收集器;专门作用于老年代的收集器有Serial Old 收集器,Parallel Old 收集器和 CMS 收集器;而 G1 收集器即能够作用于年轻代,也能够作用于老年代。 学习者需要对这 7 种垃圾回收器进行理解,并掌握其作用的内存区域。 |
|