JVM学习-垃圾回收(二)

news2024/11/20 21:20:47
标记-清除(Mark-Sweep)算法

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

  • 标记:Collector从引用根节点开始遍历,标记所有被引用的对象。一般是在对象的Header中记录为可达对象
  • 清除:Collector对堆内从头到尾进行线性的遍历,如果发现某个对象在其Header中没有标记为可达对象,则将其回收。
  • 缺点
    • 效率不算高
    • 在进行GC的时候,需要停止整个应用程序,导致用户体验差
    • 这种方式清除出来的空闲内存是不连续的,产生内存碎片,需要维护一个空闲列表
  • 何为清除
    • 这里所谓的清除并不是真的置空,而是把需要清除的对象地址保存在空闲的地址列表里,下次有新对象需要加载时,判断垃圾的位置空间是否够,如果够,就存放
      在这里插入图片描述
复制算法

将活着的内存空间分为两块,每次只使用其中一块,在垃圾回收时将正在使用的内存中的存活对象复制到未使用的内存块中,之后清除正在使用的内存块中的所有对象,交换两个内存的角色,最后完成垃圾回收。

  • 优点
  • 没有标记和清除过程,实现简单,运行高效
  • 复制过去以后保证空间的连续性,不会出现“碎片”问题
  • 缺点
    • 此算法的缺点也是很明显,就是需要两倍的内存空间
    • 对于G1这种分拆成为大量region的GC,复制而不是移动,意味着GC需要维护region之前对象引用关系,不管是内存占用或者时间开销也不小
    • 如果系统中的垃圾对象很多,复制算法需要复制的存活对象数量并不会太大,或者说非常低才行。
      在这里插入图片描述
标记-压缩(整理)Mark-Compact算法

标记清除算法的确可以应用在老年代中,但是该算法不仅执行效率低下,而且执行完内存回收后还会产生内存碎片,所以JVM设计者需要在此基础上进行改进,标记-压缩算法由此诞生

  • 执行过程
    • 第一阶段和标记清除算法一样,从根节点开始标记所有被引用对象
    • 第二阶段将所有的存活对象压缩到内存的一端,按顺序排放,之后清理边界外所有的空间
  • 标记压缩算法等同于标记清除算法执行完成后,再进行一次内存碎片整理,因此也称为标记-清除-压缩算法
  • 二者本质差异在于标记-清除算法是一种非移动式的回收算法,标记-压缩是移动式的,是否移动回收后的存活对象是一项优缺点并存的风险决策
  • 可以看到,标记存活对象将会被整理,按照内存地址依次排列,而未被标记的内存会被清理掉,如此一来,当我们需要给新对象分配内存时,JVM只需要持有一个内存的起始地址即可,比维护一个空闲列表显然少了许多开销
  • 优点
    • 消除了标记-清除算法当中,内存区域分散的缺点,我们需要给新对象分配内存时,JVM只需要一个内存起始地址即可
    • 消除了复制算法当中,内存减半的高额代价
  • 缺点
  • 从效率上来说,标记-整理算法低于复制算法
  • 移动对象的同时,如果对象被其他对象引用,则还需要调整引用的地址
  • 移动过程中,需要全程暂停用户应用程序,即STW
算法对比

在这里插入图片描述
效率上来说,复制算法是当之无愧的老大,但是却浪费了太多内存,拿空间换时间
而为了尽量兼顾上面提到的三个指标,标记-整理算法相对来说更平滑一些,但是效率上不尽如人意,它比复制算法多了一个标记的阶段,比标记-清除多了一个整理内存阶段。

分代收集算法
  • 不同对象的生命周期是不一样的,因此,不同生命周期的对象可以采取不同的收集方式,以便提高回收效率。一般是把Java堆分为新生代和老年代,这样可以根据各个年代的特点使用不同的回收算法,以提高垃圾回收的效率
  • 在Java程序运行过程中,会产生大量的对象,其中有些对象是与业务信息相关,比如http请求中的Session对象、线程、socket连接,这类对象跟业务直接挂钩,因此生命周期比较长,但还有一些对象,主要程序运行时生成的临时变量,这些对象生命周期比较短,比如String对象,由于其不变类的特性,系统会产生大量的这些对象,有些对象甚至只用一次即可回收
  • 年轻代
    • 年轻代特点,区域相对老年代较小,对象生命周期短,存活率低,回收频繁
    • 这种情况复制算法的回收整理,速度是最快的,复制算法的效率只和当前存活对象大小有关,因此很适用于年轻代的回收,而复制算法内存利用率不高的问题,通过hotspot中的两个Survivor的设计得到缓解
  • 老年代
  • 老年代特点:区域较大,对象生命周期长、存活率高,回收不及年轻代频繁
  • 这种情况存在大量存活率高的对象,复制算法明显变得不合适,一般由标记-清除或标记-整理的混合实现
  • Mark阶段的开销与存活对象的数量成正比
  • Sweep阶段的开销与所管理区域的大小成正相关
  • Compact阶段的开销与存活对象的数据成正比
增量收集算法

如果一次性将所有的垃圾进行处理,需要造成系统长时间的停顿,那么就可以让垃圾收集线程和应用程序线程交替执行。每次,垃圾收集线程只收集一小片区域的内存空间,接着切换到应用程序线程。依次反复,直到垃圾收集完成。
总的来说,增量收集算法的基础仍是传统的标记-清除和复制算法,增量收集算法通过对线程间冲突的妥善处理,允许垃圾收集线程以分阶段的方式完成标记、清理或复制工作

  • 缺点
  • 由于垃圾回收过程中,间断性地还执行了应用程序代码,所以能够减少系统的停顿时间,但是,因为线程切换和上下文转换的消耗,会使用得垃圾回收的总体成本上升,造成系统吞吐量的下降
分区算法
  • 一般来说,在相同条件下,堆空间越大,一次GC时所需要的时间就越长,有关GC产生的停顿也越长,为了更好的控制GC产生的停顿时间,将一块大的内存分割成多个小块,根据目标的停顿时间,每次合理的回收若干个小区间,而不是整个堆空间,从而减少一次GC所产生的停顿
  • 分代算法将按照对象的生命周期长短划分成两个部分,分区算法将整个堆空间划分成连续的不同小区间
  • 每个小区间都独立使用,独立回收,这种算法的好处是可以控制一次回收多少个小区间

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/1682857.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

fork 与 vfork 的区别

关键区别一: vfork 直接使用父进程存储空间,不拷贝。 关键区别二: vfork保证子进程先运行,当子进程调用exit退出后,父进程才执行。 我们可以定义一个cnt,在子进程中让它变成3, 如果使用fork,那…

java 8--Lambda表达式,Stream流

目录 Lambda表达式 Lambda表达式的由来 Lambda表达式简介 Lambda表达式的结构 Stream流 什么是Stream流? 什么是流呢? Stream流操作 中间操作 终端操作 Lambda表达式 Lambda表达式的由来 Java是面向对象语言,除了部分简单数据类型…

【机器学习】前沿探索,如何让前端开发更加搞笑

在当今数字化时代,机器学习的崛起为前端开发带来了巨大的机遇和挑战。随着人工智能和数据科学的不断进步,前端工程师不再局限于传统的界面设计和交互体验,而是开始探索如何将机器学习技术融入到他们的工作中,以创造更加智能、个性…

适合暑期做的赚钱副业兼职有哪些?盘点6个适合暑期做的赚钱副业

随着夏日的热浪滚滚而来,学生们纷纷结束了忙碌的学期,迎来了盼望已久的暑假。你是否想过在这个长假里,除了享受阳光、海滩和美食外,还能顺便赚点零用钱呢? 今天,就为大家揭秘六大神秘副业,让你在…

【漏洞复现】海康威视综合安防管理平台 iSecure Center applyCT fastjson 远程代码执行

0x01 漏洞名称 海康威视综合安防管理平台 iSecure Center applyCT fastjson 远程代码执行 0x02 漏洞影响 0x03 搜索引擎 app"HIKVISION-综合安防管理平台"0x04 漏洞详情 POST /bic/ssoService/v1/applyCT HTTP/1.1 User-Agent: Mozilla/5.0 (Windows NT 10.0; Wi…

程序语言基础知识

文章目录 1.程序设计语言2. 程序设计语言的特点和分类3. 编译程序(编译器)的工作原理4. 程序语言的数据成分4.1 数据成分4.2 运算成分4.3 控制成分4.4 传输成分 1.程序设计语言 低级语言:机器语言和汇编语言。 机器语言:二进制代…

正确可用--Notepad++批量转换文件编码为UTF8

参考了:Notepad批量转换文件编码为UTF8_怎么批量把ansi转成utf8-CSDN博客​​​​​​https://blog.csdn.net/wangmy1988/article/details/118698647我参考了它的教程,但是py脚本写的不对. 只能改一个.不能实现批量更改. 他的操作步骤没问题,就是把脚本代码换成我这个. #-*-…

浅谈后端整合Springboot框架后操作基础配置

boot基础配置 现在不访问端口8080 可以吗 我们在默认启动的时候访问的是端口号8080 基于属性配置的 现在boot整合导致Tomcat服务器的配置文件没了 我们怎么去修改Tomcat服务器的配置信息呢 配置文件中的配置信息是很多很多的... 复制工程 保留工程的基础结构 抹掉原始…

yolov8训练自己数据集时出现loss值为nan。

具体原因目前暂未寻找到。 解决办法 将参数amp改成False即可。 相关资料: https://zhuanlan.zhihu.com/p/165152789 https://github.com/ultralytics/ultralytics/issues/1148

声纹识别在无人机探测上的应用

无人机在民用和军事领域的应用越来越广泛。然而,随着无人机数量的增加,"黑飞"现象也日益严重,对公共安全和隐私构成了威胁。因此,开发有效的无人机探测与识别技术变得尤为重要。及时发现黑飞无人机的存在进而对其型号进…

自动驾驶决策规划算法——二次规划

自动驾驶决策规划算法第二章第二节(中) 参考线算法_哔哩哔哩_bilibili 动态规划开辟的凸空间如下,两条橙色线之间: 黄色的点就意味着L的上下界,物理意义是当轨迹ss1时,L的范围应该是(Lmin1,Lmax1)之间,这个范围就是开辟…

逻辑漏洞靶场通关

会员中心注册新用户test,密码123123 会员中心注册新用户name,密码abcabc 管理员账号admin,密码123456 1.普通账号间水平越权漏洞测试 一个网站登录普通账号test后修改信息时进行抓包 在重发器中修改普通账号test为普通账号name,并…

给树莓派配置静态IP地址

第一步:查找默认网关 打开windowr;输入cmd, 输入 最后一行就是默认网关 ipconfig第二步:确定分配好给树莓派的IP地址 要注意:(1)静态ip地址与路由器网段保持一致(2)与…

Linux操作系统最著名的两大系列Red Hat和Debian

Linux操作系统可以根据其背后的项目或社区分为不同的系列,其中最著名的两大系列是Red Hat系列和Debian系列。 1.著名的两大系列是Red Hat和Debian Red Hat系列: Red Hat Enterprise Linux (RHEL):这是Red Hat公司推出的企业级操作系统&#…

数据库同步软件,天不生PanguSync万古如长夜

在信息时代的海洋中,数据是那永不熄灭的灯塔,照亮了科技发展的航道。然而,随着数据的膨胀和应用场景的多样化,如何确保这些宝贵资源在不同平台、不同设备间实时更新、保持一致性,便成了一道亟待解决的难题。于是&#…

SSM【Spring SpringMVC Mybatis】—— SpringMVC

目录 1、初识SpringMVC 1.1 SpringMVC概述 1.2 SpringMVC处理请求原理简图 2、SpringMVC搭建框架 2.1 搭建SpringMVC框架 3、RequestMapping详解 3.1 RequestMapping注解位置 3.2 RequestMapping注解属性 3.3 RequestMapping支持Ant 风格的路径(了解&#…

摄像头应用测试

作者简介: 一个平凡而乐于分享的小比特,中南民族大学通信工程专业研究生在读,研究方向无线联邦学习 擅长领域:驱动开发,嵌入式软件开发,BSP开发 作者主页:一个平凡而乐于分享的小比特的个人主页…

单向无头链表实现

目录 1. 为什么要有链表? 2. 链表的种类 3. 具体功能实现 (1)节点结构体定义 (2)申请节点 (3)尾插 (4)尾删 (5)头插 (6&#…

CST电磁软件工作室时域求解器和频域求解器介绍【仿真入门】

时域求解器vs.频域求解器 不同情形下选择Time Domain Solver还是Frequency Domain Solver? 三维电磁仿真支持的具有代表性的两种求解器-Time Domain Solver和Frequency DomainSolver以不同的方式计算出仿真结果,所以根据仿真的情形可以选择性地使用两个Solver。 …

BCD编码Java实现

最常用的BCD编码,就是使用"0"至"9"这十个数值的二进码来表示。这种编码方式,在称之为“8421码”(日常所说的BCD码大都是指8421BCD码形式)。除此以外,对应不同需求,各人亦开发了不同的编…