58.垃圾清除阶段-标记-清除算法、复制算法、标记-压缩算法

2024-05-29 16:38

本文主要是介绍58.垃圾清除阶段-标记-清除算法、复制算法、标记-压缩算法,希望对大家解决编程问题提供一定的参考价值,需要的开发者们随着小编来一起学习吧!

目录

  • 1.标记-清除算法
  • 2.复制算法
  • 3.标记-压缩算法
  • 4.3种算法的对比

当成功区分出内存中的存活对象和死亡对象后,GC接下来的任务就是垃圾回收,释放掉无用对象所占用的内存空间,以便有足够的可用空间为新对象分配内存。
目前JVM中有3种常见的垃圾收集算法:标记-清除算法、复制算法、标记-压缩算法。
在这里插入图片描述

1.标记-清除算法

  1. 当堆中的有效内存空间被耗尽的时候,就会停止整个程序(Stop the World),然后进行两项工作,第一项是标记,第二项是清除。
    标记:Collector从引用根节点开始变量,标记所有被引用的对象,也就是标记出可达对象,并在对象的Header助攻记录为可达对象。
    清除:Collector对堆内存从头到尾进行线性的遍历,如果发现某个对象在其Header中没有被标记为可达对象,则将其回收。
    在这里插入图片描述
    绿色方块是存活对象,因为从根节点都可达,黑色方块是垃圾对象,白色方块是空闲空间。Collector对堆内存从头到尾进行线性的遍历,对垃圾对象进行回收。
    在这里插入图片描述

优缺点:

  1. 效率不算高。(标记阶段需要递归遍历找出可达对象,清除阶段需要线性遍历堆中所有对象,清除垃圾对象。)
  2. 在进行GC的时候,需要停止整个应用程序,导致用户体验差。
  3. 这种方式清理出来的内存空间是不连续的,产生内存碎片。需要维护一个空闲列表记录空闲空间有哪些。
    在这里插入图片描述
    何为清除?
    清除并不是真的置空(也就是对象数据并没有被真正的删除),而是把需要清除的对象地址保存在空闲的地址列表里、下次有新的对象时,判断垃圾对象的位置空间是否够,够就直接存放。

2.复制算法

  1. 将活着的内存空间划分为两块,每次只使用其中一块,在垃圾回收时将正在使用的内存中的存活对象复制到未被使用的内存块中,之后清除正在使用的内存块中的所有对象,交换两个内存的角色,最后完成垃圾回收。
    在这里插入图片描述
  2. 如下图所示,将内存区域划分为AB两个区域,A区域是正在使用的内存,B区是没有使用的内存区域。在寻找可达对象的时候,将可达对象直接复制到B区,然后回收A区中的所有对象。这时候B区变成了正在使用的区域,A区成为了空闲区域,B区中的对象现在是线性排列的。
    在这里插入图片描述

优点:

  1. 没有标记和清除过程,实现简单,运行高效
  2. 复制之后保证了 空间的连续性,不会出现“碎片”问题

缺点:

  1. 需要两倍的内存空间,有一块空间是没有使用的
  2. 复制对象之后,需要修改栈中对象的引用变量地址(因为对象被复制到了另外的空间),复制对象也会消耗不少的时间。
    特别的,如果系统中的存活对象很多(极端情况下,所有的对象都是存活对象),复制算法如果进行复制的话,效率会很低。
    在这里插入图片描述

应用:
新生代的对象基本上都是朝生夕死的,所以可达对象是很少的,非常适合复制算法。新生代里面的S0区和S1区,就应用了复制算法。
在这里插入图片描述

3.标记-压缩算法

  1. 老年代使用标记-压缩算法。压缩就是会进行碎片整理,回收之后的内存不存在碎片。
    在这里插入图片描述
  2. 执行过程
    第一阶段是标记阶段,和标记-清除算法一样,也就是递归遍历对象,找到可达对象,设置Header里面的信息。
    第二阶段是压缩阶段,将所有存活对象压缩到内存的一端,按顺序排放。之后清理剩余的空间。
    在这里插入图片描述
  3. 标记-压缩算法可以理解成在标记-清除算法执行之后,再进行一次内存碎片整理。二者的本质差异在于标记-清除算法是一种非移动式的算法,而标记-压缩算法是移动式的。
  4. 可以看到,被标记的存活的对象会被整理,按照内存地址依次排列,而未被标记的内存会被清理掉。如此一来,当需要给新对象分配内存时,JVM只需要维护一个可用内存的起始地址就可以,比维护一个空闲列表少了许多开销。
    在这里插入图片描述
    优缺点:
    在这里插入图片描述

4.3种算法的对比

在这里插入图片描述

更多JVM文章请访问我的JVM专栏:
https://blog.csdn.net/u011069294/category_10113093.html

这篇关于58.垃圾清除阶段-标记-清除算法、复制算法、标记-压缩算法的文章就介绍到这儿,希望我们推荐的文章对编程师们有所帮助!



http://www.chinasem.cn/article/1014066

相关文章

SpringBoot实现MD5加盐算法的示例代码

《SpringBoot实现MD5加盐算法的示例代码》加盐算法是一种用于增强密码安全性的技术,本文主要介绍了SpringBoot实现MD5加盐算法的示例代码,文中通过示例代码介绍的非常详细,对大家的学习... 目录一、什么是加盐算法二、如何实现加盐算法2.1 加盐算法代码实现2.2 注册页面中进行密码加盐2.

Java时间轮调度算法的代码实现

《Java时间轮调度算法的代码实现》时间轮是一种高效的定时调度算法,主要用于管理延时任务或周期性任务,它通过一个环形数组(时间轮)和指针来实现,将大量定时任务分摊到固定的时间槽中,极大地降低了时间复杂... 目录1、简述2、时间轮的原理3. 时间轮的实现步骤3.1 定义时间槽3.2 定义时间轮3.3 使用时

SQL Server清除日志文件ERRORLOG和删除tempdb.mdf

《SQLServer清除日志文件ERRORLOG和删除tempdb.mdf》数据库再使用一段时间后,日志文件会增大,特别是在磁盘容量不足的情况下,更是需要缩减,以下为缩减方法:如果可以停止SQLSe... 目录缩减 ERRORLOG 文件(停止服务后)停止 SQL Server 服务:找到错误日志文件:删除

如何通过Golang的container/list实现LRU缓存算法

《如何通过Golang的container/list实现LRU缓存算法》文章介绍了Go语言中container/list包实现的双向链表,并探讨了如何使用链表实现LRU缓存,LRU缓存通过维护一个双向... 目录力扣:146. LRU 缓存主要结构 List 和 Element常用方法1. 初始化链表2.

通过Python脚本批量复制并规范命名视频文件

《通过Python脚本批量复制并规范命名视频文件》本文介绍了如何通过Python脚本批量复制并规范命名视频文件,实现自动补齐数字编号、保留原始文件、智能识别有效文件等功能,听过代码示例介绍的非常详细,... 目录一、问题场景:杂乱的视频文件名二、完整解决方案三、关键技术解析1. 智能路径处理2. 精准文件名

linux如何复制文件夹并重命名

《linux如何复制文件夹并重命名》在Linux系统中,复制文件夹并重命名可以通过使用“cp”和“mv”命令来实现,使用“cp-r”命令可以递归复制整个文件夹及其子文件夹和文件,而使用“mv”命令可以... 目录linux复制文件夹并重命名我们需要使用“cp”命令来复制文件夹我们还可以结合使用“mv”命令总

golang字符串匹配算法解读

《golang字符串匹配算法解读》文章介绍了字符串匹配算法的原理,特别是Knuth-Morris-Pratt(KMP)算法,该算法通过构建模式串的前缀表来减少匹配时的不必要的字符比较,从而提高效率,在... 目录简介KMP实现代码总结简介字符串匹配算法主要用于在一个较长的文本串中查找一个较短的字符串(称为

通俗易懂的Java常见限流算法具体实现

《通俗易懂的Java常见限流算法具体实现》:本文主要介绍Java常见限流算法具体实现的相关资料,包括漏桶算法、令牌桶算法、Nginx限流和Redis+Lua限流的实现原理和具体步骤,并比较了它们的... 目录一、漏桶算法1.漏桶算法的思想和原理2.具体实现二、令牌桶算法1.令牌桶算法流程:2.具体实现2.1

Linux使用dd命令来复制和转换数据的操作方法

《Linux使用dd命令来复制和转换数据的操作方法》Linux中的dd命令是一个功能强大的数据复制和转换实用程序,它以较低级别运行,通常用于创建可启动的USB驱动器、克隆磁盘和生成随机数据等任务,本文... 目录简介功能和能力语法常用选项示例用法基础用法创建可启动www.chinasem.cn的 USB 驱动

Python中的随机森林算法与实战

《Python中的随机森林算法与实战》本文详细介绍了随机森林算法,包括其原理、实现步骤、分类和回归案例,并讨论了其优点和缺点,通过面向对象编程实现了一个简单的随机森林模型,并应用于鸢尾花分类和波士顿房... 目录1、随机森林算法概述2、随机森林的原理3、实现步骤4、分类案例:使用随机森林预测鸢尾花品种4.1