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

相关文章

深入理解Mysql OnlineDDL的算法

《深入理解MysqlOnlineDDL的算法》本文主要介绍了讲解MysqlOnlineDDL的算法,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的朋友们下面随着小... 目录一、Online DDL 是什么?二、Online DDL 的三种主要算法2.1COPY(复制法)

Python内存管理机制之垃圾回收与引用计数操作全过程

《Python内存管理机制之垃圾回收与引用计数操作全过程》SQLAlchemy是Python中最流行的ORM(对象关系映射)框架之一,它提供了高效且灵活的数据库操作方式,本文将介绍如何使用SQLAlc... 目录安装核心概念连接数据库定义数据模型创建数据库表基本CRUD操作创建数据读取数据更新数据删除数据查

C#利用Free Spire.XLS for .NET复制Excel工作表

《C#利用FreeSpire.XLSfor.NET复制Excel工作表》在日常的.NET开发中,我们经常需要操作Excel文件,本文将详细介绍C#如何使用FreeSpire.XLSfor.NET... 目录1. 环境准备2. 核心功能3. android示例代码3.1 在同一工作簿内复制工作表3.2 在不同

Docker多阶段镜像构建与缓存利用性能优化实践指南

《Docker多阶段镜像构建与缓存利用性能优化实践指南》这篇文章将从原理层面深入解析Docker多阶段构建与缓存机制,结合实际项目示例,说明如何有效利用构建缓存,组织镜像层次,最大化提升构建速度并减少... 目录一、技术背景与应用场景二、核心原理深入分析三、关键 dockerfile 解读3.1 Docke

C#文件复制异常:"未能找到文件"的解决方案与预防措施

《C#文件复制异常:未能找到文件的解决方案与预防措施》在C#开发中,文件操作是基础中的基础,但有时最基础的File.Copy()方法也会抛出令人困惑的异常,当targetFilePath设置为D:2... 目录一个看似简单的文件操作问题问题重现与错误分析错误代码示例错误信息根本原因分析全面解决方案1. 确保

MySQL 临时表与复制表操作全流程案例

《MySQL临时表与复制表操作全流程案例》本文介绍MySQL临时表与复制表的区别与使用,涵盖生命周期、存储机制、操作限制、创建方法及常见问题,本文结合实例代码给大家介绍的非常详细,感兴趣的朋友跟随小... 目录一、mysql 临时表(一)核心特性拓展(二)操作全流程案例1. 复杂查询中的临时表应用2. 临时

MySQL实现多源复制的示例代码

《MySQL实现多源复制的示例代码》MySQL的多源复制允许一个从服务器从多个主服务器复制数据,这在需要将多个数据源汇聚到一个数据库实例时非常有用,下面就来详细的介绍一下,感兴趣的可以了解一下... 目录一、多源复制原理二、多源复制配置步骤2.1 主服务器配置Master1配置Master2配置2.2 从服

MySQL配置多主复制的实现步骤

《MySQL配置多主复制的实现步骤》多主复制是一种允许多个MySQL服务器同时接受写操作的复制方式,本文就来介绍一下MySQL配置多主复制的实现步骤,具有一定的参考价值,感兴趣的可以了解一下... 目录1. 环境准备2. 配置每台服务器2.1 修改每台服务器的配置文件3. 安装和配置插件4. 启动组复制4.

使用Go实现文件复制的完整流程

《使用Go实现文件复制的完整流程》本案例将实现一个实用的文件操作工具:将一个文件的内容完整复制到另一个文件中,这是文件处理中的常见任务,比如配置文件备份、日志迁移、用户上传文件转存等,文中通过代码示例... 目录案例说明涉及China编程知识点示例代码代码解析示例运行练习扩展小结案例说明我们将通过标准库 os

Java中的雪花算法Snowflake解析与实践技巧

《Java中的雪花算法Snowflake解析与实践技巧》本文解析了雪花算法的原理、Java实现及生产实践,涵盖ID结构、位运算技巧、时钟回拨处理、WorkerId分配等关键点,并探讨了百度UidGen... 目录一、雪花算法核心原理1.1 算法起源1.2 ID结构详解1.3 核心特性二、Java实现解析2.