JVM中的垃圾收集算法详解(标记清除算法、标记复制算法、标记整理算法)

简介: 说到垃圾收集器必须要提的就是垃圾收集算法,因为所有的垃圾收集器都是基于垃圾收集算法实现的,垃圾收集算法是垃圾收集器的方法论,了解了这些方法论,对垃圾收集器的工作原理也就清楚了。说到垃圾收集算法,那么必须得提分代收集理论,因为有了分代收集理论才有了垃圾收集算法。

垃圾收集算法详解



说到垃圾收集器必须要提的就是垃圾收集算法,因为所有的垃圾收集器都是基于垃圾收集算法实现的,垃圾收集算法是垃圾收集器的方法论,了解了这些方法论,对垃圾收集器的工作原理也就清楚了。说到垃圾收集算法,那么必须得提分代收集理论,因为有了分代收集理论才有了垃圾收集算法。


点击查看分代收集理论的建立下面介绍下jvm中我们用到的垃圾收集算法


1.标记-清除算法


什么是标记-清除算法?


最早出现也是最基础的垃圾收集算法便是“标记-清除算法”该算法分为标记、清除两部分,回收对象时先标记待清除对象,标记完成后清除这些被标记的对象(也可以标记存活对象,清除未被标记的对象),标记的过程就是判定对象是否是垃圾的过程(使用可达性分析算法)而且后续的垃圾收集算法大多都是以“标记-清除算法”为基础进行改进的。


优点:


最基础简单的垃圾收集算法,为后续垃圾收集算法奠定了基础。


缺点:


①.执行效率不稳定,随着对象的不断增多,该算法的标记、清除的效率就会不断下降,造成执行效率不稳定,比如新生代中绝大部分对象都是朝生夕灭的,就不适合这种算法。②.内存空间碎片化,标记清除过后会产生大量不连续的内存碎片,空间碎片太多会导致再需要分配大对象时找不到合适的空间,从而提前或频繁出发GC。


应用:


“标记-清除算法”的实现最常用的就是CMS了,该垃圾收集器的收集区域是老年代(下一篇详细介绍这两种垃圾收集器)(下一篇分详细介绍这一种垃圾收集器)。


20210225191207232.png


2.标记-复制算法


什么是标记-复制算法?


将内存划分为大小相等的两块,每次只使用其中一块,当第一块内存使用完了,就把这块内存上的对象复制到另一块未使用的内存上,然后清空第一块内存,这种回收对象的算法被称为“标记-复制算法”,该算法是基于“标记-清除算法”演变而来。


优点:


①解决了“标记-清除算法”的执行效率不稳定问题,该算法主要应用于新生代,新生代对象大部分都是朝生夕灭的,新生代被划分为Eden、From Survivor、To Survivor,每次使用Eden和一个Survivor用于新生对象的存储。 垃圾回收时就把Eden、From Survivor中存活的对象复制到另一个Survivor上,这样便不会有执行效率不稳定的情况,因为大部分对象都是朝生夕灭的(该优点是相对于新生代来说)。②解决了“标记-清除算法”的空间碎片化问题,因为是清空Eden From Survivor所以不会再有不连续的空间碎片。


缺点:


①“标记-复制算法”因为必须有一部分空间时刻空闲着,所以会有一定的空间浪费,②在极端情况下To Survivor区域不一定能存储的了新生代存活下来的对象,所以需要分配担保策略(对象进入老年代)。


应用:


“标记-复制算法”实现常用的有:Serial、ParNew、Parallel Scavenge。这三款垃圾收集器收集目标都是新生代(下一篇详细介绍这三种垃圾收集器)。

20210225191234925.png


3.标记-整理算法


什么是标记-整理算法?


“标记-复制算法”有他的自身缺陷,这种场景很适合新生代,但对于大部分对象都是存活下来的老年代就不适用了,老年代中对象存活过多,复制动作的内存开销就会很大,所以针对老年代的特性,提出了“标记-整理算法”,标记动作与“标记-清除算法”、“标记-复制算法”中的标记一样都是使用的可达性分析算法对对象进行标记,整理部分则是将存活的对象向内存空间一端进行移动,然后直接清理掉边界以外的内存区域。


优点:


①解决了“标记-清除算法”的空间碎片化问题。②解决了“标记-复制算法”需要分配担保的问题。


缺点:


根据强分代假说“熬过越多次垃圾收集的对象,越难以被回收”,老年代中的大部分对象都是年龄达到了16的对象,都是很难被回收的,所以采用“标记-整理算法”去移动对象,对应用程序的吞吐量其实影响很大,但是不得不使用“标记-整理算法”,因为“标记-清除算法”会浪费一定空间,“标记-复制算法”又必须有分配担保策略也需要浪费空间,且“标记-复制算法”也无法满足老年代中所有对象都存活的极端情况。


应用:


“标记-整理算法”实现常用的有:Serial Old、Parallell Old。这两款垃圾收集器的收集目标都是老年代(下一篇详细介绍这两种垃圾收集器)。  



20210225191304939.png


4.对比标记-清除算法与标记-整理算法


为什么单独比较这两种算法呢,因为老年代中既有使用“标记-清除算法”实现的CMS垃圾收集器,也有使用“标记-整理算法”实现的Serial Old、Parallel Old等垃圾收集器,而“标记-复制算法”在典型情况下只用于新生代(G1是例外,这是一种区别于典型垃圾收集器的收集器),所以这里之比较这两种算法的优劣,“标记-清除算法”与“标记-整理算法”的根本区别在于在回收对象时,对象是否发生了移动,换种说法就是,“标记-清除算法”是一种非移动式的垃圾收集算法,而“标记-整理算法”是一种移动式的垃圾收集算法。在“标记-清除算法”中因为对象不移动,只是清除被标记的对象,这样就产生了很多的空间碎片,致使在新对象进来时会导致可能没有足够的空间进行存储新对象,从而提前或频繁触发GC,而且因为空间是碎片化的,对象的分配必须依赖“空闲列表”,每次对象进来要先通过空闲列表来查找堆中哪些区域是空闲且足够该对象的分配,无形中就增加了程序的时间成本,降低应用的吞吐量,所以CMS作为“标记-清除算法”实现的垃圾收集器更为关注的是STW状态的延时,而不是应用程序的吞吐量,总结一句话“标记-清除算法”在分配对象阶段更为复杂,“标记-整理算法”是移动式回收算法,在老年代中大部分对象都是存活的,因此在回收对象时,会伴随大量的对象移动,从而会导致对象回收阶段会占用相对多的时间,因此采用“标记-整理算法”实现的Parallel Old是更为关注吞吐量的一款垃圾收集器,总结一句话,“标记-整理算法”在回收对象阶段更为复杂。

相关文章
|
1月前
|
缓存 算法 Java
JVM知识体系学习六:JVM垃圾是什么、GC常用垃圾清除算法、堆内存逻辑分区、栈上分配、对象何时进入老年代、有关老年代新生代的两个问题、常见的垃圾回收器、CMS
这篇文章详细介绍了Java虚拟机(JVM)中的垃圾回收机制,包括垃圾的定义、垃圾回收算法、堆内存的逻辑分区、对象的内存分配和回收过程,以及不同垃圾回收器的工作原理和参数设置。
65 4
JVM知识体系学习六:JVM垃圾是什么、GC常用垃圾清除算法、堆内存逻辑分区、栈上分配、对象何时进入老年代、有关老年代新生代的两个问题、常见的垃圾回收器、CMS
|
1月前
|
存储 监控 算法
JVM调优深度剖析:内存模型、垃圾收集、工具与实战
【10月更文挑战第9天】在Java开发领域,Java虚拟机(JVM)的性能调优是构建高性能、高并发系统不可或缺的一部分。作为一名资深架构师,深入理解JVM的内存模型、垃圾收集机制、调优工具及其实现原理,对于提升系统的整体性能和稳定性至关重要。本文将深入探讨这些内容,并提供针对单机几十万并发系统的JVM调优策略和Java代码示例。
51 2
|
1月前
|
算法 Java
JVM进阶调优系列(4)年轻代和老年代采用什么GC算法回收?
本文详细介绍了JVM中的GC算法,包括年轻代的复制算法和老年代的标记-整理算法。复制算法适用于年轻代,因其高效且能避免内存碎片;标记-整理算法则用于老年代,虽然效率较低,但能有效解决内存碎片问题。文章还解释了这两种算法的具体过程及其优缺点,并简要提及了其他GC算法。
 JVM进阶调优系列(4)年轻代和老年代采用什么GC算法回收?
|
1月前
|
存储 算法 Java
【JVM】垃圾释放方式:标记-清除、复制算法、标记-整理、分代回收
【JVM】垃圾释放方式:标记-清除、复制算法、标记-整理、分代回收
50 2
|
1月前
|
缓存 算法 Java
GC垃圾收集算法
这篇文章详细讨论了垃圾收集(GC)的几种算法,包括引用计数、可达性分析、标记-清除、标记-复制和标记-整理算法,并介绍了这些算法的优缺点和适用场景。
27 0
GC垃圾收集算法
|
3月前
|
存储 算法 Java
JVM自动内存管理之垃圾收集算法
文章概述了JVM内存管理和垃圾收集的基本概念,提供一个关于JVM内存管理和垃圾收集的基础理解框架。
JVM自动内存管理之垃圾收集算法
|
3月前
|
存储 算法 Java
JVM组成结构详解:类加载、运行时数据区、执行引擎与垃圾收集器的协同工作
【8月更文挑战第25天】Java虚拟机(JVM)是Java平台的核心,它使Java程序能在任何支持JVM的平台上运行。JVM包含复杂的结构,如类加载子系统、运行时数据区、执行引擎、本地库接口和垃圾收集器。例如,当运行含有第三方库的程序时,类加载子系统会加载必要的.class文件;运行时数据区管理程序数据,如对象实例存储在堆中;执行引擎执行字节码;本地库接口允许Java调用本地应用程序;垃圾收集器则负责清理不再使用的对象,防止内存泄漏。这些组件协同工作,确保了Java程序的高效运行。
27 3
|
3月前
|
C# UED 开发者
WPF打印功能实现秘籍:从页面到纸张,带你玩转WPF打印技术大揭秘!
【8月更文挑战第31天】在WPF应用开发中,打印功能至关重要,不仅能提升用户体验,还增强了应用的实用性。本文介绍WPF打印的基础概念与实现方法,涵盖页面元素打印、打印机设置及打印预览。通过具体案例,展示了如何利用`PrintDialog`和`PrintDocument`控件添加打印支持,并使用`PrinterSettings`类进行配置,最后通过`PrintPreviewWindow`实现打印预览功能。
336 0
|
3月前
|
C# UED 开发者
WPF动画大揭秘:掌握动画技巧,让你的界面动起来,告别枯燥与乏味!
【8月更文挑战第31天】在WPF应用开发中,动画能显著提升用户体验,使其更加生动有趣。本文将介绍WPF动画的基础知识和实现方法,包括平移、缩放、旋转等常见类型,并通过示例代码展示如何使用`DoubleAnimation`创建平移动画。此外,还将介绍动画触发器的使用,帮助开发者更好地控制动画效果,提升应用的吸引力。
188 0
|
3月前
|
算法 Java 程序员
【JVM的秘密花园】揭秘垃圾收集器的神秘面纱!
【8月更文挑战第25天】在Java虚拟机(JVM)中,垃圾收集(GC)自动管理内存,回收未使用的对象以避免内存泄漏和性能下降。本文深入介绍了JVM中的GC算法,包括串行、并行、CMS及G1等类型及其工作原理。选择合适的GC策略至关重要:小型应用适合串行收集器;大型应用或多核CPU环境推荐并行收集器或CMS;需减少停顿时间时,CMS是好选择;G1适用于大堆且对停顿时间敏感的应用。理解这些能帮助开发者优化程序性能和稳定性。
37 0