首页 > 编程语言 >JVM(十二)垃圾清除阶段算法

JVM(十二)垃圾清除阶段算法

时间:2023-07-12 10:45:33浏览次数:58  
标签:标记 对象 清除 算法 内存 JVM 垃圾

JVM(十二)垃圾清除阶段算法


  • 垃圾清除阶段是指,当成功区分出内存区域中的存活对象和死亡对象之后,GC接下来的任务就是执行垃圾回收,释放掉无用对象所占用的内存空间,以便有足够的可用内存空间为新对象分配内存

  • 目前在JVM中比较常见的三种垃圾收集算法是标记-清除算法(Mark-Sweep)复制算法(Copying)标记压缩算法(Mark-Compact)

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

image-20230705203421207
  • 标记-清除算法(Mark-Sweep)是一种非常基础和常见的垃圾收集算法

  • 当堆中的有效内存空间被耗尽的时候,就会停止整个程序(Stop The World),然后进行两项工作,第一项是标记,第二项是清除:

    • 标记Collector从引用根节点开始遍历,标记所有被引用的对象,一般是在对象的Header中记录为可达对象(递归遍历部分对象)

    • 清除Collector对堆内存从头到尾进行线性的遍历,如果发现某个对象在其Header中没有被标记为可达对象,则将其回收(线性遍历全部对象)

      这里的清除并不是真的置空清除,而是把需要清除的对象地址保存在空闲的地址列表里面,当下次有新的对象加载的时候,就判断垃圾的位置空间是否足够,如果够就存放,本质是覆盖原有垃圾对象

  • 标记-清除算法(Mark-Sweep)的缺点:

    • 效率不算高
    • 在进行GC的时候,需要停止整个应用程序,导致用户的体验差
    • 这种方式清理出来的内存空间会产生内存碎片,因此是不连续的,需要额外维护一个空闲列表

2 复制算法(Copying)

image-20230709111531542
  • 复制算法的核心思想是:将活着的内存空间分为两块,在垃圾回收的时候将正在使用的内存空间中活着的对象复制到未被使用的内存块中,之后清除正在使用的内存块中的对象,交换两个内存块的角色完成垃圾回收

  • 新生代的内存空间中的幸存者0幸存者1区的垃圾清除就是使用的这种复制算法

  • 优点:

    • 没有标记和清除的过程,实现简单、运行高效
    • 复制过去之后能够保证空间的连续性,因此不会出现碎片问题

    没有标记过程指的是不需要在存活对象的Header中添加存活记录,仅仅只需要通过根可达算法将可达对象复制到另一个内存区域即可

  • 缺点:

    • 需要两倍的内存空间
    • 对于G1这种垃圾收集器,会将内存拆分成为大量的分区(region),复制意味着GC需要维护分区之间的对象引用关系,导致产生内存占用和时间开销
    • 复制算法的高效性是建立在存活对象少、垃圾对象多的前提下的,否则如果像老年代一样大多数对象都是存活对象的话,依然使用复制算法就会导致复制的成本特别高

3 标记-压缩算法(Mark-Compact)

image-20230709144421782
  • 标记-压缩算法是为了解决标记-清除算法复制算法的缺点而设计的:

    • 复制算法适用于新生代而不适用于老年代大多数情况对象都是存活对象的情况
    • 标记-清除算法可以应用在老年代中,但是该算法的效率低下,而且在执行完内存回收后还会产生内存碎片,不利于老年代大对象的存储,所以标记-压缩算法在此基础上进行了改进
  • 执行过程

    • 第一阶段从根节点开始标记所有被引用的对象,和标记-清除算法一样
    • 第二阶段将所有的存活对象都压缩到内存的一端,并按照顺序排放
    • 最后,清理边界以外的所有空间
  • 标记-压缩算法的最终效果等同于标记-清除算法执行完成后,再进行一次内存碎片整理,因此也可以称之为标记-清除-压缩算法

    二者的本质差异在于标记-清除算法是一种非移动式的回收算法,标记-压缩是移动式的。是否移动回收后的存回对象是一种优缺点并存的风险决策

  • 标记的存活对象按照内存地址整理排列之后,再给新对象分配内存的时候,只需要存储一个内存的起始地址即可,而不需要再维护一个空闲列表

  • 优点:

    • 消除了标记-清除算法内存区域分散的缺点,需要给新对象分配内存的时候,只需要存储一个内存的起始地址即可,而不需要再维护一个空闲列表
    • 避免了复制算法内存减半的代价
  • 缺点:

    • 标记-压缩算法的效率低于复制算法
    • 移动过程中,如果对象被其他对象引用,则需要调整引用的地址
    • 移动过程需要STW,全程暂停用户应用程序

4 三种算法的比较

标记-清除算法 复制算法 标记-压缩算法
速度 中等 最快 最慢
空间开销 少(但会堆积内存碎片) 通常需要存活对象的两倍大小(不会堆积内存碎片) 少(不会堆积内存碎片)
移动对象

标签:标记,对象,清除,算法,内存,JVM,垃圾
From: https://www.cnblogs.com/tod4/p/17546907.html

相关文章

  • JVM(十一)垃圾回收概述和垃圾标记阶段的算法
    JVM(十一)垃圾回收概述和垃圾标记阶段的算法1Java垃圾回收概述什么是垃圾?垃圾是在程序运行过程中不被任何指针指向的对象,这个对象就是需要被回收的垃圾为什么要进行垃圾回收?如果不及时对内存中的垃圾进行清理,那么这些垃圾对象所占内存空间会一直保存到应用程序结束,被......
  • 初识虚拟机JVM
    初识JVM(JAVAVirtualMachine)​ JVM是一种规范,可以使用软件来实现,也可以使用硬件来实现,就是一个虚拟的用于执行bytecodes字节码的计算机。他也定义了指令集、寄存器集、结构栈、垃圾收集堆、内存区域。​ JVM负责将java字节码解释运行,边解释边运行,这样,速度就会受到一定的影......
  • Day05_垃圾回收机制
    1.Day04的温故知新: 2.今日内容: 3.列表在内存当中存值的方式: 4.1.直接引用和间接引用: 4.2.直接引用和间接引用: 5.1.标记清除_循环引用: ......
  • 算法学习day14二叉树part01-94、144、145
    packageSecondBrush.Tree;importjava.util.ArrayList;importjava.util.List;/***94.二叉树的中序遍历*给定一个二叉树的根节点root,返回它的中序遍历。**/publicclassBinaryTreeInorderTraversal_94{publicList<Integer>inorderTraversal(Tre......
  • 数据结构与算法 #18 下跳棋,极富想象力的同向双指针模拟
    ⭐️本文已收录到AndroidFamily,技术和职场问题,请关注公众号[彭旭锐]和[BaguTreePro]知识星球提问。学习数据结构与算法的关键在于掌握问题背后的算法思维框架,你的思考越抽象,它能覆盖的问题域就越广,理解难度也更复杂。在这个专栏里,小彭将基于Java/Kotlin语言,为你分享常......
  • 浅谈BIT本科数据结构与算法课程 1
    关于C++基本输入输出流#include<bits/stdc++.h>usingnamespacestd;intmain(){ inta,b; cin>>a>>b; cout<<a<<endl; return0;}栈和队列关于stl#include<algorithm>vector<int>x;x.push_back(n);x.pop_back();x.back();x[1......
  • JVM(六)堆
    JVM(六)堆1核心概述几乎所有的对象实例和数组都是分配在堆上的(栈不会存储数组和对象,栈帧中的局部变量表只会存储指向堆中实例的引用)一个Java进程对应一个JVM实例,一个JVM实例只存在一个堆内存,堆也是内存管理的核心区域堆和方法区是线程共享的,但堆也有划分的线程私有缓冲区......
  • 负载均衡算法的选择
    负载均衡算法的选择应该根据具体的应用场景和需求来确定。以下是一些常见的负载均衡算法及其适用场景:轮询(RoundRobin):适用于请求处理时间相对均匀的场景,能够实现简单的请求分配。加权轮询(WeightedRoundRobin):适用于不同后端服务器性能不同的场景,可以根据服务器的性能设置不同......
  • C++进制转换+扫描线算法(二维区间合并面积和)
    ......
  • 代码随想录算法训练营第二十九天| 1005.K次取反后最大化的数组和 134. 加油站 135. 分
      860.柠檬水找零 思路:遇到20,先给10和5,再给三个5代码:1boollemonadeChange(vector<int>&bills){2if(bills.size()==0)returntrue;34map<int,int>currentMoney;5for(inti=0;i<bills.size();i++)6{7if......