深入理解 Java 虚拟机 学习:总结 GC 的知识点,面试问 GC 有这一篇就足够了

Java 虚拟机 其他相关博客

深入理解 Java 虚拟机 学习:Java虚拟机内存区域
深入理解 Java 虚拟机 学习:对象访问

引用资料地址

垃圾收集算法与垃圾收集器
Java常见面试题—GC垃圾收集器
7种垃圾收集器
《 深入理解 Java 虚拟机:JVM高级特性与最佳实践》

GC

介绍
GC垃圾收集,Java提供的GC可以自动监测对象是否超过作用域从而达到自动回收内存的目的。
垃圾回收可有效使用内存和防止内存泄露。垃圾回收器通常是作为一个单独的低优先级线程运行,不可预知的情况下对内存堆中已死亡或长久无使用的对象进行清除和回收。

回收机制:分代复制垃圾回收、标记垃圾回收、增量垃圾回收等方式。

1.GC是如何判断对象是否存活

  • 引用计数算法
    介绍:给每一个对象添加一个引用计数器,当有引用指向对象时,计数器加一,引用移除时,计数器减一,当计数器为0时,说明对象未被引用,可以回收
    存在问题:两个对象互相引用,此时不会被回收。
    使用:java虚拟机不采用

  • 根搜索算法
    介绍:通过一系列的名为“GC Roots”的对象作为起点,从这些节点向下搜索,经过的路径称为引用链,当一个对象没有引用链即是可回收状态。
    java语言中的GC Roots 的对象包括

    1.虚拟机栈中的引用对象
    2.方法区中的类静态属性引用的对象
    3.方法区常量引用的对象
    4.本地方法栈中JNI的引用对象

    使用:java虚拟机采用

2.引用

  • 介绍:如果 reference 类型的数据中存储的数值代表的是另外一块内存的起始地址,就称这块内存代表着一个引用
  • 分类:强引用,软引用,弱引用,虚引用
    强引用:强引用就是指在程序代码中普遍存在的,类似 Object obj = new Object() 这类的引用,只要强引用还存在,垃圾收集器永远都不会回收掉被引用的对象
    软引用:软引用用来描述一些还有用,但非必需的对象。对于软引用关联着的对象,在系统将要发生内存溢出异常之前,将会把这些对象列进回收范围之中并进行第二次回收,如果这次回收还是没有足够的内存,才会抛出内存溢出异常。
    弱引用:弱引用也是用来描述非必须对象的,但是它的强度比软引用更弱一些,被弱引用关联的对象只能生存到下一次垃圾手机发生之前。当垃圾收集器工作时,无论当前内存是否足够,都会回收掉被弱引用关联的对象。
    虚引用:虚引用也称为幽灵引用或者幻影引用,它是最弱的一种引用关系。一个对象是否有虚引用的存在,完全不会对其生存时间构成影响,也无法通过虚引用来取得一个对象实例。为一个对象设置虚引用关联的唯一目的就是希望能在这个对象被收集器回收时收到的一个系统通知。

3.GC是如何判断对象是否存活

一个对象真正死亡至少要经过两次标记

  • 第一次标记:经过根搜索发现没有与 GC Roots 相链接的引用链
    标记条件:是否有必要执行 finalize() 方法,对象没有覆盖 finalize() 方法,或 finalize() 方法已经被虚拟机调用过,虚拟机将这两种情况视为 没有必要执行。被标记的对象将会放入一个 F-Queue 队列中等待第二次标记
  • 第二次标记:GC 对 F-Queue 进行第二次小规模标记,这个过程中对象重新与引用链上的任何一个对象建立关联,获得生存,否则死亡。

注意:所有对象的finalize()方法只会执行一次,如果对象面临下一次回收,它的 finalize() 方法不会被再次执行,自救行动失败

4.垃圾收集算法

4.1 标记 - 清除算法(Mark-Sweep)

介绍:标记-清除算法分为两个阶段为标记阶段清除阶段。标记阶段的任务是标记出所有需要被回收的对象,清除阶段就是回收被标记的对象所占用的空间
缺点
1.效率问题:标记和清楚过程的效率都不高
2.空间问题:标记清除之后会产生大量不连续的内存碎片,导致当程序在以后的运行过程中需要分配较大对象时无法找到足够的连续内存而不得不提前触发另一次垃圾收集动作。
深入理解 Java 虚拟机 学习:总结 GC 的知识点,面试问 GC 有这一篇就足够了_第1张图片

4.2 复制算法(Copying)

介绍:为了解决标记 - 清除算法的缺陷,复制算法就被提了出来。它将可用内存按容量划分为大小相等的两块,每次只使用其中的一块。当这一块的内存用完了,就将还存活着的对象复制到另外一块上面,然后再把已使用的内存空间一次清理掉,这样一来就不容易出现内存碎片的问题
优点:每次都是对其中的一块进行内存回收,内存分配时也就不用考虑内存碎片等复杂情况,只要移动堆顶指针,按顺序分配内存即可,实现简单,运行高效
缺点:这种算法的代价是将内存缩小为原来的一半,代价高昂
深入理解 Java 虚拟机 学习:总结 GC 的知识点,面试问 GC 有这一篇就足够了_第2张图片

4.3 标记 - 整理算法(Mark-Compact)

介绍:为了解决复制算法的缺陷,充分利用内存空间,提出了标记-整理算法。该算法标记阶段和标记-清除算法一样,但是在完成标记之后,它不是直接清理可回收对象,而是将存活对象都向一端移动,然后清理掉端边界以外的内存。
深入理解 Java 虚拟机 学习:总结 GC 的知识点,面试问 GC 有这一篇就足够了_第3张图片

4.4 分代收集算法(Generational Collection)

介绍:当前商业虚拟机的垃圾收集都采用分代收集算法,根据对象的存活周期的不同将内存划分为几块。一般是把 Java 堆分为新生代和老年代,根据各个年代的特点采用最适合的收集算法。
备注:在新生代中,每次垃圾收集时都发现有大批对象死去,只有少量存活,选用复制算法。在老年代中因为对象存活率搞,没有额外空间对他进行分配担保,就必须使用标记-清除算法标记-整理算法来进行回收
注意:在堆区之外还有一个代就是永久代(Permanet Generation),它用来存储class类、常量、方法描述等。对永久代的回收主要回收两部分内容:废弃常量无用的类

5.吞吐量

介绍:吞吐量就是 CPU 用于运行用户代码的时间与 CPU 总消耗时间的比例,而高吞吐量可以高效率地利用 CPU 时间,尽快地完成程序的运算任务,主要适合在后台运算而不需要太多交互的任务
公式:吞吐量就是 CPU 用于运行用户代码的时间与 CPU 总消耗时间的比例,即 吞吐量 = 运行用户代码时间 / (运行用户代码时间 + 垃圾收集时间),虚拟机总共运行了 100 分钟 ,其中垃圾收集花费 1 分钟,那吞吐量就是 99%

6.垃圾收集器

介绍:GC收集算法是内存回收的方法论,垃圾收集器是内存回收的具体实现。Java虚拟机规范中对垃圾收集器应该如何实现并没有任何规定,因此不同的厂商、不同版本的虚拟机所提供的垃圾收集器都可能会有很大差别,并且一般都会提供参数供用户根据自己应用的特点和要求组合出各个年代所使用的收集器。
注意:如果两个收集器之间存在连线,就说明它们可以搭配使用
深入理解 Java 虚拟机 学习:总结 GC 的知识点,面试问 GC 有这一篇就足够了_第4张图片

6.1.Serial 收集器

介绍新生代(年轻代)收集器,单线程进行垃圾回收,回收时会导致Stop The World,用户进程停止,可以和Serial Old、CMS组合使用
算法:复制算法
线程:单线程收集器
优点:简单而高效
缺点:它在进行垃圾收集时,必须暂停其他所有工作线程,直到它收集结束。比如电脑运行一小时就会暂停响应五分钟
深入理解 Java 虚拟机 学习:总结 GC 的知识点,面试问 GC 有这一篇就足够了_第5张图片

6.2.ParNew 收集器

介绍:ParNew 收集器就是 Serial 收集器的多线程版本,它也是一个新生代收集器。除了使用多线程进行垃圾收集外,其余行为包括 Serial 收集器可用的所有控制参数、收集算法(复制算法)、Stop The World、对象分配规则、回收策略等与 Serial 收集器完全相同,两者共用了相当多的代码。
算法:收集算法(复制算法)
线程:多线程收集器
优点:除了 Serial 收集器外,目前只有它能和CMS收集器(Concurrent Mark Sweep)配合工作。CPU 的数量增加时,它对于 GC 时系统资源的有效利用是很有好处的,它默认开启的收集线程数与 CPU 的数量相同,在 CPU 非常多的情况下可使用 -XX:ParallerGCThreads 参数设置
缺点:ParNew 收集器在单CPU的环境中绝对不会有比 Serial 收集器有更好的效果,甚至由于存在线程交互的开销,该收集器在通过超线程技术实现的两个CPU的环境中都不能百分之百地保证可以超越
深入理解 Java 虚拟机 学习:总结 GC 的知识点,面试问 GC 有这一篇就足够了_第6张图片

6.3.Parallel Scavenge 收集器

介绍:Parallel Scavenge 也是一个新生代收集器,看上去和 ParNew 收集器差不多,区别在于 Parallel Scavenge 的 目标是达到一个可控制的吞吐量,Parallel Scavenge 收集器提供了两个参数用于精确控制吞吐量,分别是控制最大垃圾收集停顿时间的 -XX:MaxGCPauseMillis 参数及直接设置吞吐量大小的 -XX:GCTimeRatio 参数
算法:复制算法
线程:多线程收集器
关于吞吐量

  1. -XX:MaxGCPauseMillis:设置大于 0 的毫秒数,收集器尽可能在该时间内完成垃圾回收
  2. -XX:GCTimeRatio:大于 0 小于 100 的整数,即垃圾回收时间占总时间的比率,设置越小则希望垃圾回收所占时间越小,CPU 能花更多的时间进行系统操作,提高吞吐量
  3. -XX:UseAdaptiveSizePolicy:参数开关,启动后系统动态自适应调节各参数,如 -Xmn、-XX:SurvivorRatio 等参数,这是和 ParNew 收集器重要的区别

优点:Parallel Scavenge 通过控制吞吐量,从而达到可以高效率地利用 CPU 时间,尽快地完成程序的运算任务
缺点:使用多线程进行垃圾回收,回收时会导致Stop The World

6.4.Serial Old 收集器

介绍:Serial Old 收集器是 Serial 收集器的老年代版本,这个收集器主要意义也就是被 Client 模式下的虚拟机使用
线程:单线程收集器
算法:标记 - 整理算法,会对垃圾回收导致的内存碎片进行整理
两大用途

  1. 是在 JDK 1.5 及之前的版本中与 Parallel Scavenge 收集器搭配使用
  2. 作为 CMS 收集器的后备预案,在并发收集发生 Concurrent Mode Failure 的时候使用

深入理解 Java 虚拟机 学习:总结 GC 的知识点,面试问 GC 有这一篇就足够了_第7张图片

6.5.Parallel Old 收集器

介绍:Parallel Old 收集器是 Parallel Scavenge 收集器的老年代版本,这个收集器是在 JDK 1.6 中才开始提供的,在此之前,新生代的 Parallel Scavenge 收集器一直处于比较尴尬的状态。原因是,如果新生代选择了 Parallel Scavenge 收集器,老年代除了 Serial Old 收集器外别无选择。所以在 Parallel Old 诞生以后,“吞吐量优先”收集器终于有了比较名副其实的应用组合,在注重吞吐量以及CPU资源敏感的场合,都可以优先考虑Parallel Scavenge加Parallel Old收集器
线程:多线程收集器
算法:标记 - 整理算法,会对垃圾回收导致的内存碎片进行整理
深入理解 Java 虚拟机 学习:总结 GC 的知识点,面试问 GC 有这一篇就足够了_第8张图片

6.6.CMS 收集器

介绍:CMS 收集器是 一种以获取最短回收停顿时间为目标的收集器。目前很大一部分的 Java 应用都集中在互联网站或 B/S 系统的服务端上,这些应用都非常重视服务的响应速度
线程
算法:标记 - 清除,可以通过设置参数在垃圾回收时进行内存碎片的整理
运作过程

  1. 初始标记:仍然需要 Stop the World 用户进程停顿,仅仅标记一下 GC Roots 能直接关联到的对象,速度快
  2. 并发标记:进行 GC Roots Tracing 的过程,而重新标记阶段则是为了修改并发标记时间,因为用户程序继续运作而导致标记产生变动的那一部分对象的标记记录,也就是时间长。不发生用户进程停顿
  3. 重新标记:仍然需要 Stop the World 用户进程停顿,修正并发标记期间因用户程序继续运行导致标记变动的那一部分对象的标记记录,停顿时间较长,但远比并发标记时间短
  4. 并发清除:清除的同时用户进程会导致新的垃圾,时间长,不发生用户进程停顿

优点:并发收集、低停顿,因此CMS收集器也被称为并发低停顿收集器 。适合于对响应时间要求高的系统
缺点

  1. 对CPU资源非常敏感
  2. CMS收集器无法处理浮动垃圾,即清除时用户进程同时产生的垃圾,只能等到下次GC时回收
  3. 因为是使用“标记-清除”算法,所以会产生大量碎片

深入理解 Java 虚拟机 学习:总结 GC 的知识点,面试问 GC 有这一篇就足够了_第9张图片

6.7.G1 收集器

介绍:G1(Garbage-First)收集器是当今收集器技术发展最前沿的成果之一,它是一款面向服务端应用的垃圾收集器,HotSpot开发团队赋予它的使命是(在比较长期的)未来可以替换掉JDK 1.5中发布的CMS收集器
算法:标记 - 整理算法,也就是说不会产生空间碎片,对长时间运行的应用系统来说非常重要
特点

  1. 因为基于标记 - 整理算法实现的收集器,也就是说它不产生空间碎片,对于长时间运行的应用系统来说异常的重要 。
  2. 可以非常精确的控制停顿,技能让使用者明确指定在一个长度为 M 毫秒的时间片段内,消耗在垃圾收集上的时间也不得超过 N 毫秒。
  3. G1 收集器可以实现在基本不牺牲吞吐量的前提下完成低停顿的内存回收,这是由于它能够极力地避免全区域的垃圾收集,之前收集器进行收集的范围都是整个新生代或老年代,而 G1 将整个 Java 堆(包括新生代,老年代)划分成多个大小固定的独立区域,并且跟踪这些区域里面的垃圾堆积成度,在后台维护一个优先级列表,酶促根据允许的收集时间,优先回收垃圾最多的区域

深入理解 Java 虚拟机 学习:总结 GC 的知识点,面试问 GC 有这一篇就足够了_第10张图片

总结

收集器 线程 新生代/老年代 算法 优先 适用场景
Serial 收集器 串行 新生代 复制算法 响应速度优先 单CPU环境下的Client模式
ParNew 收集器 并行 新生代 复制算法 响应速度优先 多CPU环境时在Server模式下与CMS配合
Parallel Scavenge 收集器 并行 新生代 复制算法 吞吐量优先 在后台运算而不需要太多交互的任务
Serial Old 收集器 串行 老年代 标记-整理 响应速度优先 单CPU环境下的Client模式、CMS的后备预案
Parallel Old 收集器 并行 老年代 标记-整理 吞吐量优先 在后台运算而不需要太多交互的任务
CMS 收集器 并发 老年代 标记-清除 响应速度优先 集中在互联网站或B/S系统服务端上的Java应用
G1 收集器 并发 All 标记-整理+复制算法 响应速度优先 面向服务端应用,将来替换CMS

你可能感兴趣的:(JVM,jvm,面试,java)