当前位置: 首页 > news >正文

GC垃圾回收介绍及GC算法详解

目录

引言

GC的作用域

什么是垃圾回收?

常见的GC算法

1.引用计数法

2.复制算法

3.标记清除

4.标记整理

小总结

5.分代收集算法

ps:可达性分析算法?

可达性分析的作用

可达性分析与垃圾回收算法的关系

结论


引言

在编程世界中,内存管理是一个至关重要的话题。对于使用自动内存管理的语言(如Java、Python、Go等),垃圾回收(Garbage Collection, GC)机制是确保程序高效运行的关键。本文将介绍垃圾回收的基本概念,并详细讲解四种常见的垃圾回收算法。


GC的作用域

记住GC口诀: 分代收集算法

次数频繁Young区,次数较少Old区,基本不动Perm(永久区)区


什么是垃圾回收?

垃圾回收是一种自动内存管理机制,用于识别和释放不再被程序使用的内存。其主要目的是防止内存泄漏,减少程序员手动管理内存的负担,并提高程序的稳定性和性能。

先看下一个对象的历程:

JVM 在进行GC时,并非每次都对上面三个内存区域一起回收的,大部分时候回收的都是指新生代

因此GC按照回收的区域又分了两种类型,一种是普通的GC(minor GC),一种是全局GC (major GC or Full GC)

普通GC(轻GC):只针对新生代区域的GC

全局GC(重GC):针对老年代的GC,偶尔伴随对新生代的GC以及对永久代的GC


常见的GC算法

1.引用计数法

每个对象有一个引用计数器,当对象被引用一次则计数器加1,当对象引用失效一次,则计数器减1,对 于计数器为0的对象意味着是垃圾对象,可以被GC回收。


2.复制算法

年轻代中使用的是Minor GC,采用的就是复制算法

Minor GC 会把Eden中的所有活的对象都移到Survivor区域中,如果Survivor区中放不下,那么剩下的 活的对象就被移动到Old generation中,也就是说,一旦收集后,Eden就是变成空的了 当对象在Eden(包括一个Survivor区域,这里假设是From区域)出生后,在经过一次Minor GC后,如 果对象还存活,并且能够被另外一块Survivor区域所容纳 (上面已经假设为from区域,这里应为to区 域,即to区域有足够的内存空间来存储Eden 和 From 区域中存活的对象),则使用复制算法将这些仍然 还活着的对象复制到另外一块Survivor区域(即 to 区域)中,然后清理所使用过的Eden 以及Survivor 区域(即form区域),并且将这些对象的年龄设置为1,以后对象在Survivor区,每熬过一次Minor GC,就将这个对象的年龄 + 1,当这个对象的年龄达到某一个值的时候(默认是15岁,通过 XX:MaxTenuringThreshold 设定参数)这些对象就会成为老年代。

-XX:MaxTenuringThreshold  任期门槛=>设置对象在新生代中存活的次数

面试题:如何判断哪个是to区呢?一句话:谁空谁是to

工作原理

  • 将内存分为两个相等的区域:From空间和To空间。

  • 复制阶段:从From空间复制所有存活对象到To空间。

  • 清理阶段:清空From空间,然后交换From和To空间的角色。

优点

  • 简单高效,没有内存碎片问题。

缺点

  • 需要双倍内存空间,适用于存活对象较少的情况。


3.标记清除

说明:老年代一般是由标记清除或者是标记清除与标记整理的混合实现

什么是标记清除? 回收时,对需要存活的对象进行标记; 回收不是绿色的对象

当堆中的有效内存空间被耗尽的时候,就会停止整个程序(也被称为stop the world),然后进行两项 工作,第一项则是标记,第二项则是清除。

标记:从引用根节点开始标记所有被引用的对象,标记的过程其实就是遍历所有的GC Roots ,然后将所 有GC Roots 可达的对象,标记为存活的对象。

清除: 遍历整个堆,把未标记的对象清除。

缺点:这个算法需要暂停整个应用,会产生内存碎片。

工作原理

  • 标记阶段:从根对象(如全局变量、栈中的对象)出发,遍历所有可达对象,并标记它们为存活。

  • 清除阶段:遍历整个堆内存,释放未被标记的对象所占用的内存。

优点

  • 实现简单,适用于大多数场景。

缺点

  • 会产生内存碎片,可能导致后续内存分配效率降低。


4.标记整理

在整理压缩阶段,不再对标记的对象作回收,而是通过所有存活对象都像一端移动,然后直接清除边界 以外的内存。可以看到,标记的存活对象将会被整理,按照内存地址依次排列,而未被标记的内存会被 清理掉,如此一来,当我们需要给新对象分配内存时,JVM只需要持有一个内存的起始地址即可,这比 维护一个空闲列表显然少了许多开销。

标记、整理算法不仅可以弥补 标记、清除算法当中,内存区域分散的缺点,也消除了复制算法当中,内 存减半的高额代价;

工作原理

  • 标记阶段:与标记-清除算法相同,标记所有存活对象。

  • 整理阶段:将所有存活对象移动到内存的一端,然后清理边界以外的内存。

优点

  • 解决了内存碎片问题,提高了内存利用率。

缺点

  • 整理阶段需要移动对象,增加了时间开销。


小总结

内存效率:复制算法 > 标记清除算法 > 标记整理算法 (时间复杂度)

内存整齐度:复制算法 = 标记整理算法 > 标记清除算法

内存利用率:标记整理算法 = 标记清除算法 > 复制算法

可以看出,效率上来说,复制算法是当之无愧的老大,但是却浪费了太多内存,而为了尽量兼顾上面所提到的三个指标,标记整理算法相对来说更平滑一些 , 但是效率上依然不尽如人意,它比复制算法多了 一个标记的阶段,又比标记清除多了一个整理内存的过程

难道就没有一种最优算法吗?猜猜看,下面还有

答案 : 无,没有最好的算法,只有最合适的算法 。 -----------------> 分代收集算法

5.分代收集算法

工作原理

  • 基于对象的生命周期将内存分为不同的代(如年轻代和老年代)。

  • 年轻代:使用复制算法,因为大多数对象在年轻代中很快死亡。

  • 老年代:使用标记-清除或标记-整理算法,因为老年代中的对象存活时间较长。

优点

  • 针对不同生命周期的对象采用不同的回收策略,提高了回收效率。

缺点

  • 实现复杂,需要维护多个代的内存区域。


ps:可达性分析算法?

可达性分析算法(Reachability Analysis)本身并不是一个独立的垃圾回收算法,而是一种用于判断对象是否存活的技术。它是许多垃圾回收算法的基础,尤其是**标记-清除算法(Mark-Sweep)和标记-整理算法(Mark-Compact)**的核心部分。

可达性分析的作用

可达性分析通过从根对象(如全局变量、栈中的局部变量、静态变量等)出发,遍历所有被引用的对象,标记这些对象为“存活”。未被标记的对象则被认为是“垃圾”,可以被回收。

可达性分析与垃圾回收算法的关系

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

    • 使用可达性分析来标记所有存活对象。

    • 在清除阶段,释放未被标记的对象的内存。

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

    • 同样使用可达性分析来标记存活对象。

    • 在整理阶段,将存活对象移动到内存的一端,然后清理剩余的内存。

  • 分代收集算法(Generational)

    • 在年轻代和老年代中,都可能使用可达性分析来判断对象的存活状态。

    • 年轻代通常使用复制算法,而老年代可能使用标记-清除或标记-整理算法。

  • 复制算法(Copying)

    • 虽然复制算法的主要特点是复制存活对象,但它也需要通过可达性分析来确定哪些对象是存活的。


结论

垃圾回收是现代编程语言中不可或缺的一部分,它通过自动管理内存,极大地简化了程序开发。不同的垃圾回收算法各有优缺点,适用于不同的应用场景。理解这些算法的原理和适用场景,有助于我们编写更高效、更稳定的程序。

http://www.lryc.cn/news/544407.html

相关文章:

  • 2020 年英语(一)考研真题 笔记(更新中)
  • 【springboot】Spring 官方抛弃了 Java 8!新idea如何创建java8项目
  • playbin之autoplug_factories源码剖析
  • 正浩创新内推:校招、社招EcoFlow社招内推码: FRQU1CY
  • 一文了解:部署 Deepseek 各版本的硬件要求
  • 有没有什么免费的AI工具可以帮忙做简单的ppt?
  • python绘图之灰度图
  • 华为 VRP 系统简介配置SSH,TELNET远程登录
  • 1.14 重叠因子:TRIMA三角移动平均线(Triangular Moving Average, TRIMA)概念与Python实战
  • 【tplink】校园网接路由器如何单独登录自己的账号,wan-lan和lan-lan区别
  • PC 端连接安卓手机恢复各类数据:安装、操作步骤与实用指南
  • 【折线图 Line】——1
  • SpringBoot 整合mongoDB并自定义连接池,实现多数据源配置
  • TCP/IP的分层结构、各层的典型协议,以及与ISO七层模型的差别
  • FreeRTOS-中断管理
  • ShenNiusModularity项目源码学习(15:ShenNius.Admin.API项目分析)
  • Express + MongoDB 实现文件上传
  • 计算机毕业设计SpringBoot+Vue.js作业管理系统(源码+文档+PPT+讲解)
  • Odoo免费开源CRM技术实战:从商机线索关联转化为售后工单的应用
  • 2025年如何实现安卓、iOS、鸿蒙跨平台开发
  • 萌新学 Python 之 os 模块
  • IPoIB源码深度解析:如何基于TCP/IP协议栈实现高性能InfiniBand通信
  • 本地部署阿里万象2.1文生视频模型(Wan2.1-T2V)完全指南
  • information_schema.processlist 表详解
  • P8623 [蓝桥杯 2015 省 B] 移动距离
  • 2025年Linux主力系统选择指南:基于最新生态的深度解析(附2025年发行版对比速查表)
  • [密码学实战]Java实现国密(SM2)密钥协商详解:原理、代码与实践
  • 015--基于STM32F103ZET6的智能风扇设计
  • 基于YOLO11深度学习的遥感视角农田检测与分割系统【python源码+Pyqt5界面+数据集+训练代码】深度学习实战、目标分割、人工智能
  • RBF神经网络+NSGAII多目标优化算法,工艺参数优化、工程设计优化(Matlab)