`
wanxiaotao12
  • 浏览: 476605 次
  • 性别: Icon_minigender_1
  • 来自: 北京
社区版块
存档分类
最新评论

HotSpot 垃圾回收算法实现 转

    博客分类:
  • JVM
 
阅读更多

转自:http://coderbee.net/index.php/jvm/20131105/557

 

《深入理解Java虚拟机:JVM高级特性与最佳实践》-笔记

垃圾回收算法

枚举根结点

一致性

在可达性分析期间整个系统看起来就像被冻结在某个时间点上,不可以出现分析过程中对象引用关系还在不断变化的情况。

一致性要求导致GC进行时必须停顿所有Java执行线程。(Stop The World)
即使在号称不会发生停顿的CMS收集器中,枚举根节点时也是必须停顿的。

HotSpot使用的是准确式GC,当执行系统停顿下来后,并不需要一个不漏地检查完所有执行上下文和全局的引用位置,这是通过一组称为OopMap的数据结构来达到的。

在类加载完成后,HotSpot就把对象内什么偏移量上是什么类型的数据计算出来;在JIT编译过程中,也会在特定的位置记录下栈和寄存器中哪些位置是引用。

安全点(Safe Point)

程序只有在到达安全点时才能暂停。安全点的选定标准是“是否具有让程序长时间执行的特征”。“长时间执行”的最明显特征就是指令序列的复用,如方法调用、循环跳转等,具有这些功能的指令才会产生安全点。

让程序暂停的两种方式

  • 抢先式中断(Preemptive Suspension):在GC发生时,主动中断所有线程,不需要线程执行的代码主动配合。几乎不被采用。

  • 主动式中断(Voluntary Suspension):设一个标志,各个线程主动去轮询这个标志,遇到中断则暂停。轮询地方与安全点重合。

安全区域(Safe Region)

指在一段代码片段中,引用关系不会发生变化。在这个区域的任意地方开始GC都是安全的。

线程执行到安全区域中的代码时,首先标识自己进入了安全区域;在离开安全区域时,要检查系统是否已经完成了枚举根节点(或整个GC过程),完成了就继续执行,否则必须等待直到收到可以安全离开Safe Region的信号。

安全区域是为了解决线程Sleep或Blocked状态的。

垃圾收集器

前面的垃圾收集算法是理论,垃圾收集器则是具体的实现。

下图是HotSpot里的收集器,中间的横线表示分代,有连线表示可以组合使用。 

Serial 收集器

是一个单线程的收集器,只能使用一个CPU或一条线程去完成垃圾收集;在进行垃圾收集时,必须暂停所有其他工作线程,直到收集完成。

Serial/Serial Old 收集器运行示意图:
Serial_gc_runtime

缺点:Stop-The-World。

优势:简单。对于但CPU的情况,由于没有多线程交互开销,反而可以更高效。

是Client模式下默认的新生代收集器。

ParNew 收集器

是Serial收集器的多线程版本。

ParNew/Serial Old 收集器运行示意图:
ParNew_gc_runtime

垃圾收集语境下的并发与并行概念

  • 并行(Parallel):指多条垃圾收集线程并行工作,用户线程仍然处于等待状态。
  • 并发(Concurrent):用户线程与垃圾收集线程同时执行。

Parallel Scavenge 收集器

新生代收集器,使用复制算法、并行的多线程收集器。

Parallel Scavenge 收集器的目标是达到一个可控制的吞吐量(Throughput)。这里的吞吐量是指CPU用于运行用户代码的时间与CPU总消耗时间的比值。主要适合在后台运算而不需要太多交互的任务。

Parallel Scavenge 收集器允许采用GC自适应的调节策略,也就是让虚拟机根据收集到的运行时数据自行决定各个分代的大小等与垃圾回收有关的配置。

Serial Old 收集器

用于老年代的Serial收集器,单线程,使用“标记-整理”算法。

SerialOld_gc_runtime

主要在Client模式下使用。

Parallel Old 收集器

Parallel Scavenge的老年代版本,多线程,使用“标记-整理”算法。

ParallelOld_gc_runtime

CMS 收集器

CMS(Concurrent Mark Sweep)收集器是一种以获取最短回收停顿时间为目标的收集器。基于“标记-清除”算法。

CMS_gc_runtime

运作过程分为4个阶段:

  • 初始标记(CMS initial mark):值标记GC Roots能直接关联到的对象。
  • 并发标记(CMS concurrent mark):进行GC RootsTracing的过程。
  • 重新标记(CMS remark):修正并发标记期间因用户程序继续运行而导致标记发生改变的那一部分对象的标记。
  • 并发清除(CMS concurrent sweep):

其中标记和重新标记两个阶段仍然需要Stop-The-World,整个过程中耗时最长的并发标记和并发清除过程中收集器都可以和用户线程一起工作。

CMS收集器对CPU资源非常敏感。

浮动垃圾(Floating Garbage):由于CMS并发清理阶段用户线程还在运行着,自然会有新的垃圾产生,而这些垃圾是在标记过程之后,CMS只能在下次GC时回收它们,这些垃圾就称为浮动垃圾。

CMS收集器无法处理浮动垃圾,可能出现“Concurrent Mode Failure”失败而导致另一次Full GC的产生。

在垃圾收集阶段用户线程还在运行,因此需要预留足够的内存给用户线程使用。如果预留内存不能满足用户线程,会出现“Concurrent Mode Failure”,这时虚拟机将启动临时后备预案:临时启用Serial Old收集器来重新进行老年代的垃圾收集。

由于CMS使用的是清除算法,会导致内存碎片问题,因此提供了参数用于控制是否在进行FullGC后进行内存整理,还提供了参数用于控制在多少次FullGC时才进行内存整理。内存整理是不能并发的,也就是要暂停所有用户线程。

G1 收集器

G1(Garbage First):是一款面向服务端应用的垃圾收集器,用于替换CMS收集器。

G1_gc_runtime

G1将整个Java堆划分为大小相等的独立区域(Region);新生代和老年代不再是物理隔离的,都由一组不连续的Region组成。

G1的特点:

  • 并行与并发:充分利用多CPU缩短Stop-The-World停顿时间,在收集过程中用并发的方式让Java线程继续执行。
  • 分代收集:仍然有分代的概念,不需要其他收集器配合,独立管理整个GC堆。
  • 空间整合:从整体看,是基于“标记-整理”算法实现的,从局部(两个Region之间)看是基于“复制”算法的。在运行期间不会产生内存碎片。
  • 可预测的停顿:G1跟踪各个Region里垃圾堆积值的价值大小,维护一个优先级队列,每次根据允许的时间,优先回收价值最大的Region。(这也是Garbage First的由来)

Region之间的对象引用以及其他收集器中的新生代与老年代之间的对象引用,虚拟机都是使用Remembered Set来避免全堆扫描的。

G1中每个Region都有一个与之对应的Remembered Set,虚拟机发现程序对引用类型的数据进行写操作时,会产生一个Write Barrier暂时中断写操作,检查引用的对象是否处于不同的Region中(在其他收集器中就是检查是否老年代中的对象引用了新生代中对象),如果是,通过CardTable把相关引用信息记录到被引用对象所属的Region的Remembered Set中。进行内存回收时,在GC根节点的枚举范围中加入Remembered Set即可保证不对全堆扫描也不会有遗漏。

G1垃圾回收主要有4个阶段:

  • 初始标记:只标记GC Roots能直接关联到的对象,并且修改TAMS(Next Top at Mark Start)值,让下一阶段用户程序并发运行时,能在正确可用的Region中创建新对象。此阶段需要暂停用户线程。
  • 并发标记:从GC Roots开始对堆中对象进行可达性分析,找出存活对象;耗时较长,可与用户线程并发执行。
  • 最终标记:修正在并发标记期间有变动的标记记录。
  • 刷选回收:对各个Region的回收价值和成本进行排序,根据用户期望的GC停顿时间制定回收计划,进行垃圾回收。

内存分配与回收规则

内存分配与回收规则由垃圾回收器和内存有关参数决定,不是固定的。

两个概念:

  • MinorGC,次收集:在新生代发生的垃圾收集,速度快,发生频繁。
  • FullGC,MajorGC,主收集:发生在年老代的垃圾收集。一般伴随一次MinorGC。

一般的规则:

  • 对象优先在Eden分配。当Eden没有足够的空间时,虚拟机将发起一次MinorGC。

  • 大对象直接进入老年代。大对象是指需要连续内存空间的Java对象。目的是避免在Eden区及两个Survivor区之间大量的内存复制(新生代采用复制算法收集内存)。

  • 长期存活对象将进入老年代。虚拟机给每个对象定义一个对象年龄计数器,如果对象在Eden出生并经过一次Minor GC后仍然存活,并且能够被Survivor容纳,将被移动到Survivor空间,并且对象年龄设为1。对象在Survivor区中每“熬过”一次MinorGC,年龄就加1,达到某个阀值就晋升到年老代。

  • 空间分配担保。在发生Minor GC之前,虚拟机会先检查年老代最大可用的连续空间算法大于新生代所有对象总空间,如果是,那么Minor GC可以确保是安全的。如果否,虚拟机会查看HandlePromotionFailure设置是否允许担保失败。如果允许继续检查老年代最大可用的连续空间是否大于历次晋升到老年代对象的平均大小,如果大于,将尝试进行一次Minor GC,这是有风险的(存活对象占用的内存大于平均大小,将导致HandlePromotionFailure失败,重新发起一次Full GC);如果小于或者HandlePromotionFailure设置不允许冒险,将改为Full GC。

分享到:
评论

相关推荐

    垃圾回收算法与实现,Turling

    《垃圾回收算法与实现》是IT领域中关于内存管理和优化的重要话题,主要关注的是如何自动地识别并释放不再使用的内存,以确保程序的稳定运行。在这个主题中,Turing垃圾回收算法是一个重要的研究方向,它在Java等语言...

    06.HotSpot算法实现1

    HotSpot算法是Java虚拟机(JVM)中的一种垃圾回收算法,主要用于回收Java对象占用的内存空间。该算法的实现主要涉及到三个重要的知识点:枚举跟节点、安全点和安全区域。 枚举跟节点是指从可达性分析中找出GC roots...

    JDK12-hotspot-virtual-machine-garbage-collection-tuning-guide

    HotSpot 虚拟机是 Oracle 公司开发的 Java 虚拟机实现,它提供了多种垃圾回收算法和策略,包括Serial GC、Parallel GC、Concurrent Mark-and-Sweep(CMS)GC、G1 GC 等。每种算法都有其优缺点,适用于不同的应用场景...

    [百度网盘] HotSpot实战[完整版][带书签].pdf

    - **不同的垃圾回收算法**:包括Serial、ParNew、Parallel Scavenge、CMS、G1等不同类型的垃圾回收器,适用于不同场景的需求。 - **垃圾回收调优**:通过合理的参数配置,如设置新生代和老年代的比例、选择合适的...

    JAVA垃圾回收面试个人总结.doc

    Java垃圾回收机制是Java编程中一个非常重要的概念,尤其在面试和实际开发中常常被讨论。垃圾回收(Garbage Collection, GC)是Java虚拟机自动管理内存的一种方式,旨在自动识别并释放不再使用的对象,从而避免内存...

    垃圾回收系列(3):CLR与JVM垃圾回收器的比较扫描.pdf

    当讨论垃圾回收(Garbage Collection,GC)时,这两个环境均有自己独特的实现方式。在本篇文章中,我们将对比CLR和JVM的垃圾回收机制,从分代机制、回收模式、回收算法到查找存活对象的技术,深入探究它们之间的异同...

    08-java11-hotspot-guide.pdf

    2. 垃圾回收:HotSpot虚拟机提供了多种垃圾回收算法,包括串行垃圾回收(Serial Garbage Collector)、并行垃圾回收(Parallel Garbage Collector)以及针对低延迟应用的G1垃圾回收器(G1 Garbage Collector)和Z...

    22G1GC:分区回收算法说的是什么?1

    分区回收算法是一种垃圾收集策略,主要应用于Java Hotspot虚拟机中的G1(Garbage-First)垃圾收集器,以及Android的ART(Apache Runtime)虚拟机。这种算法将堆内存划分为多个固定大小的区域(Region),每个Region都有...

    HotSpot实战

    2. **垃圾回收**:HotSpot 提供了多种垃圾回收算法,如 Serial Collector、Parallel Collector、CMS Collector 和 G1 Collector 等。这些垃圾回收器针对不同的应用场景进行了优化,用户可以根据自己的需求选择合适的...

    Java垃圾回收机制深度解析与代码实践

    现代JVM如HotSpot,提供了多种垃圾回收器,它们背后的实现原理基本上是上述垃圾回收算法的变体或组合。理解这些算法的基本原理,可以帮助开发者更好地理解JVM的内存管理机制,从而写出更高效、更稳定的Java应用程序...

    高吞吐低延迟Java应用的垃圾回收优化.docx

    Oracle 的 Hotspot JVM 内存管理白皮书是开始学习 Hotspot JVM GC 算法非常好的资料。 ### 2.仔细考量 GC 需求 降低应用性能的 GC 开销,优化 GC 的一些特征。吞吐量、延迟等这些 GC 特征应该长时间测试运行观察,...

    垃圾回收系列(3):CLR与JVM垃圾回收器的比较宣贯.pdf

    相比之下,JVM(以Hotspot为例)的垃圾回收更为复杂。在Client模式下,默认使用串行GC,而在Server模式下,新生代和旧生代分别使用并行GC和平行标记-清除GC。这些策略旨在平衡垃圾回收效率与应用程序的暂停时间。 ...

    垃圾回收器是什么1

    垃圾回收器是编程语言中的一个重要概念,特别是在Java和Oracle的Hotspot及OpenJDK等...不同的JVM实现,如Hotspot和OpenJDK,以及不同的编程语言,可能有不同的垃圾回收策略和实现,需要根据具体场景进行选择和调整。

    hotspot1.7.rar

    3. **垃圾回收(GC)**:Hotspot虚拟机实现了多种垃圾回收算法,如串行GC、并行GC、CMS和G1等。理解GC的工作原理、触发条件以及如何调整GC参数,能帮助解决内存管理和性能问题。 4. **内存模型**:了解Java内存模型...

    16_垃圾回收相关概念.pptx

    总之,垃圾回收是Java程序内存管理的关键组成部分,JVM通过复杂的算法和策略来优化这一过程。理解垃圾回收的工作原理和不同类型的垃圾收集器可以帮助我们编写更高效、更稳定的代码,避免不必要的资源消耗和潜在的...

    12 垃圾回收相关概念.md,学习代码

    四、垃圾回收算法 1. **复制算法**:将内存分为两块,每次只使用一块,当一块空间满时,将存活对象复制到另一块,然后清空使用过的区域。 2. **标记-清除算法**:首先标记所有活动对象,然后清除未被标记的对象。...

    hotspot-8.rar

    对于Java开发者来说,深入理解HotSpot源码能够帮助他们更好地理解和优化Java应用程序,因为这涉及到JVM如何处理内存管理、垃圾回收、类加载、线程调度等关键操作。 在Java世界中,JVM扮演着至关重要的角色,它是...

    JVM历史发展和内存回收笔记

    2. **垃圾回收算法**: - **标记-清除(Mark-Sweep)**:首先标记出所有活动对象,然后清除未标记的对象。缺点是容易产生内存碎片。 - **复制(Copying)**:将内存分为两块,每次只使用一块,当一块用完后,将...

    单例模式与垃圾回收机制

    HotSpot虚拟机主要采用分代收集理论,将堆分为年轻代(Young Generation)和老年代(Old Generation),并通过不同的算法进行垃圾回收。 #### 四、单例对象是否会被垃圾回收 ##### 4.1 争议背景 关于单例对象是否会成为...

Global site tag (gtag.js) - Google Analytics