说说JVM的垃圾回收机制

news2024/11/19 7:33:37

简介

垃圾回收机制英文为Garbage Collection, 所以我们常常称之为GC。那么为什么我们需要垃圾回收机制呢?如果大家有了解过Java虚拟机运行时区域的组成(JVM运行时存在,本地方法栈,虚拟机方法栈,程序计数器,堆,方法区五个区域),我们知道本地方法栈,虚拟机方法栈和程序计数器是线程独有的,即随着线程的存在而存在,随着线程的消亡而消亡,其内存分配和回收都具备确定性所以不用过多考虑回收问题。但是Java堆(主要存放对象)和方法区(存放常量和静态的属性,方法,对象)由于只有在运行时才知道有多少对象,所以这部分内存的分配和回收时动态的,此时就需要我们的垃圾回收机制来进行处理。

Point 1:如何判断对象是否存活

目前有两种方法来判断对象是否存活,第一种是引用计数算法,第二种是可达性分析算法。接下来我们对他们逐一进行讲解:

  • 引用计数算法:在对象中添加一个引用计数器,每当该对象被引用,计数器值就加一;引用失效就减一;当计数器为0,该对象就是不可使用的。虽然占用了一些额外空间,但是优点是效率高,但是存在一个问题,即:当两个对象互相引用时,虽然他们都不能被访问了,但是由于互相引用的原因,导致计数器为1,所以会成为漂浮垃圾,无法被回收。
  • 可达性分析算法:即在程序进行到某一点时,判断该对象能否被引用。我们可以举例结合图像来说明,本质上我们通过GC Root Set 来维护一个根集合,其中存在很多根对象节点,从这些节点向下走,经过的路径称为引用链,如若链中节点对根节点不可达,那么说明该对象不可使用了。该算法不能在应用程序活跃运行时执行对象追踪,因为执行上下文和对象图都在持续变化中,应用程序执行与可达性分析是一个竞态条件
  • 固定可做GC Roots 对象包括以下几种:
    • 在虚拟机栈中引用的对象
    • 在方法区中静态属性引用的对象
    • 在方法区中常量引用的对象
    • 在本地方法栈中JNI引用的对象
    • Java虚拟机内部的引用
    • 所有被同步锁持有的对象
    • 反射Java虚拟机内部情况的 JMXBean, JVMTI中注册的回调、本地代码缓存等

引用分类:

  1. 强引用
  2. 软引用
  3. 弱引用
  4. 幻影引用

JVM判断对象死亡过程

要真正宣布一个对象死亡需要精力两次标记过程,如若一个对象发现对于 GC Root 是不可达的,那么它将会被第一次标记。如若对象没有覆盖finalize()方法,或者finalize()方法已经被虚拟机调用过了,那么虚拟机将这两者情况视作“没必要执行”。如若对象被确定为需要进行finalize()方法,那么该对象会被放到一个称为F-Queue的队列之中,并由一个新线程去执行finalize()方法。此时虚拟机还会对F-Queue队列中的对象进行一次小规模标记,如若对象在finalize()方法中成功自救,即连接上可达GC Root 对象的节点,即可逃脱回收。

需要注意的一点是:任何一个对象的finalize()方法都只会被系统自动调用一次,意味着如果第一次逃脱了,那么第二次如果被标记就会直接回收,不在进行finalize()方法。

Point 2:垃圾收集算法

主要有两类:“引用计数式” -- 直接垃圾收集 & “追踪式垃圾收集” -- 间接垃圾收集

分代收集

根据弱分代假说强分代假说,我们的收集器应该将Java堆划分出不同的区域,然后将回收对象依据其熬过垃圾收集过程的次数将其分配到不同区域中存储。所以目前我们的Java虚拟机一般存在新生代老年代。根据跨代引用假说我们可以得知跨代引用虽然存在,但是较于同代引用只占少数,因此我们引出了一个新的数据结构——记忆集,该数据结构用于吧老年代划分为若干小块,标记老年代哪一块内存存在跨代引用,如若新生代发生了GC的话,只用将对应小块内存加入到GC Root进行扫描就ok了。

注:新生代收集(Minor GC/ Young GC) / 老年代收集(Major GC/ Old GC) / 混合收集(Mixed GC) / 整堆收集(Full GC)

说了这么多关于收集器的分代概念,大家是否对虚拟机如何进行收集有疑问呢?接下来就来说说关于虚拟机的收集算法。主要分为三种:标记清除法,标记复制法,标记整理法。

  • 标记——清除算法:顾名思义,该算法分为两步,首先标记所有需要回收的对象,在标记完成后统一回收所有被标记的对象。
    • 缺点:1. 执行效率不太稳定,会随着对象数量增长降低回收(标记和回收)效率。 2. 存在内存空间碎片化问题,由于每次标记和清楚都是碎片化的操作,这样就会引出一个问题,当我们需要分配一个大的对象的时候,就无法在新生代找到一个合适的区域放置这个对象,这时会触发另外一次垃圾回收动作。
  • 标记——复制算法:为了解决上一算法存在的缺点1,我们提出了该算法,又被称为半区复制算法,即将内存容量分为两个等大区域,每次只使用其中一块,如若被使用那块被用完了就将还存活的对象迁移至另一块内存空间,这个算法也避免了上述算法的缺点2。
    • 但是同样的这个算法也存在缺点:1. 大量的内存复制开销。2. 针对大多数对象都是存存活的状况,使用标记复制算法就欠妥了。3. 将可用内存空间变为内存的一半。
    • 所以针对新生代,朝生夕灭的特点,我们可以判断出标记复制算法可以用于新生代而且由于对象存活时间短数量少,我们可以将内存空间的划分做一些改变,比如按照 8:1 的比例进行分配,选取一个占比为 1/ 9 的空间作为固定的存放存货对象的空间。但是这样就会引出一个新问题,如果超过了 1/9 空间的对象存活,那么就存放不下了。这时我们就需要内存分配担保机制将新生代无法存放的存活对象直接存入老年代。
  • 标记——整理算法:由上文可知,标记复制算法的变型用于新生代回收特别方便,那么对于我们的老年代呢?根据老年代特性,我们知道其中大部分对象都是存活的,只会有少量对象需要回收。我们可以使用标记——整理的方法来解决,即标记活的对象,然后将存活对象移至一端,然后将须回收对象移至一端,我们就只清除这一端就ok了。但是这样也带来一个问题,既然老年代大多数对象都是存活的,那么每次这样移动操作对系统消耗较大而且也会导致"Stop The World" 发生。所以我们有了一种新的办法来处理老年代对象,即让虚拟机在大多数时间都采用标记——清除算法,知道内存碎片已经影响到对象分配了,我们就采用标记——整理算法对空间进行一次整理,得到一个规整的内存空间。

Point 3:HotSpot 算法实现细节

根节点枚举

由于需要查询对象引用关系,所有的收集器在根节点枚举这一步骤都是要暂停用户线程的。由于当前主流Java虚拟机采用的都是准确式垃圾收集,用户线程停顿后不需要逐个检查执行上下文,只需得到哪些地方存储着对象引用。例如HostSopt采用的就是OopMap来记录对象信息。

安全点

在OopMap的协助下,HotStop可以快速准确的完成GC Root枚举,但是导致OopMap变化的指令很多,如若每个都生成OopMap那么将会需要大量额外空间。事实上HotSopt也只在安全点进行OopMap生成,即只有到了安全点,才可以暂停用户线程进行GC。中断也有两种方式:

  1. 抢断式中断:抢断式中断不需要线程执行代码主动配合,发生GC时,会中断所有的用户线程,如果发现有用户线程中断的地方不在安全点上,就恢复这条线程知道他到达安全点再度中断。
  2. 主动式中断:不直接对线程操作,仅仅简单的设置一个标志位,每个线程都不停的轮询这个标志位,一旦发现标志位为中断就主动挂起。这个标志位和安全点是重合的。

安全区域

可以理解为加长版的安全点。如果程序在执行,它可以运行到安全点,如果程序不执行,如线程处于Sleep或者Blocked状态,这时候线程无法响应虚拟机中断请求,自然就无法走到安全点去挂起自己。所以安全区就是在某一段代码中,引用关系不会发生变化,因此,在这个区域中任意地方开始垃圾收集是安全的。线程进入安全区域会标识自己,离开时会检查虚拟机是否完成了根结点枚举,如若没有收到就会被要求一直等待直到收到可以离开的信号。

Point 4:记忆集与卡表

在前文中我们提到了记忆集的概念,即用于解决查询跨代引用代价过大问题而引申出来的数据结构。

定义:记忆集是一种用于记录从非收集区域指向收集区域的指针集合的抽象数据结构。

有三种精度,分别是:1.字节精度,2. 对象精度, 3. 卡精度。三者中最常用的就是卡精度,顾名思义,采用卡表来实现记忆集,它定义了记忆集的记录精度与堆内存映射关系。可以联想为Java中Map。一个卡页通常包括不止一个对象,如若卡页里面有超过一个对象字段的跨代指针,那么就将对应卡表的数组元素的值设置为1,称为这个卡表变脏(dirty) 否则就是0。

卡表变脏的实际就是有其他分代区域中的对象引用了本区域的对象时,卡表就会变脏。

Point 5:写屏障

我们知道了卡表变脏时机,那么我们将如何来将卡表更新呢?由于编译过程是机器码,所以虚拟机就不方便介入,于是在我们的HotSpot中存在一个写屏障,可以看作虚拟机层面对“引用类型字段赋值”这个动作的AOP切面,在引用对象赋值时会产生一个环形通知,赋值前后都在写屏障覆盖范畴内。

一些收集器

垃圾回收器我就不过多赘述了,本质上就是对垃圾回收算法的实践。有很多版本比如 CMS, ZGC等等,如读者有兴趣可自行搜索学习。

参考资料:

《深入理解Java虚拟机》

《虚拟机设计与实现,以JVM为例》

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

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

相关文章

第六节:使用SMB开发WebService

一、概述 webservice在日常开发中是常用的接口形式,SMB在设计之初就将webservice作为重要的代理协议。在组件库中提供了webservice input和webservice output两个组件,分别用于发布接口和调用接口。 二、发布webservice 在csdnProject工程中创建名为c…

C语言易错知识点:scanf函数

scanf在C语言学习中比较常用,但因为其涉及屏幕缓冲区导致有的时候会调入陷阱,下面分享一下常见的需要注意的事项: 1.输入末尾带有回车\n 当我们输入数据后,最后按下回车时,屏幕缓冲区的末尾都会含有这个字符 scanf的…

综合知识篇08-数据库系统考点(2024年软考高级系统架构设计师冲刺知识点总结系列文章)

专栏系列文章: 2024高级系统架构设计师备考资料(高频考点&真题&经验)https://blog.csdn.net/seeker1994/category_12593400.html案例分析篇00-【历年案例分析真题考点汇总】与【专栏文章案例分析高频考点目录】(2024年软考高级系统架构设计师冲刺知识点总结-案例…

【工具推荐】tmux 终端与会话分离神器 | 再也不用担心训练到一半不小心关闭终端导致训练终止了

文章目录 [toc] 0 什么是终端?什么是会话?1 tmux的安装2 tmux的基本操作2.1 启动与退出(杀死tmux)2.2 分离会话2.3 重接会话2.4 当前已有的会话查看2.5 切换会话 0 什么是终端?什么是会话? tmux是一个 ter…

每个私域运营者都必须掌握的 5 大关键流量运营核心打法!

很多人觉得私域运营比较简单,只是运营的事情,但事实并非如此,私域运营体系非常大,包含了公私域联动、品牌运营、品类战略,它是一个自上而下,由内到外的系统化工程。 很多人天天在想着如何引流拓客&#xf…

人民币跨境支付系统CIPS应用架构设计

人民币跨境支付系统(Cross-border Interbank Payment System,简称CIPS)作为中国重要的金 融市场基础设施之一,为境内外机构提供人民币跨境支付清算服务及其他相关服务。随着CIPS网络延伸 和规模扩大,为保障公司核心竞争…

每日一题——LeetCode1694.重新格式化电话号码

方法一 模拟: 首先去除number里面的破折号和空格,取出纯数字组成的字符串str。 对于str每三个数分成一组,加一个破折号,当str的长度小于等于4时再分情况讨论,如果等于4就分为22形式,如果小于4&#xff0c…

网络编程--高并发服务器

这里写目录标题 引入场景 多进程并发服务器二级目录二级目录二级目录 多线程并发服务器二级目录二级目录二级目录 多路IO转接服务器设计思路对比引入 select函数简介参数介绍第一个参数第234参数返回值对于第234参数的应用对于最后一个参数总结 附加操作(附加四个函…

一招搞定:教你用苹果手机截取滚屏网页

打开Safari浏览器,进入需要截取的网页。 点击屏幕底部的分享按钮,即中间有一个向上箭头的矩形图标。 在弹出的分享菜单中,向左滑动找到“截屏”选项,点击后选择“整页”。 系统会自动将网页保存为PDF文件,并自动打开…

【Redis知识点总结】(五)——Redis实现分布式锁

Redis知识点总结(五)——Redis实现分布式锁 setnxsetnx expiresetnx expire lua脚本set nx exset nx ex 随机值set nx ex 随机值 lua脚本set ex nx 随机值 lua脚本 锁续期RedissonRedLock 在Redis的众多应用场景中,分布式锁是Redis比…

Ypay源支付2.8.8免授权聚合免签系统

本帖最后由 renleixiaoxu 于 2024-3-15 09:46 编辑 产品介绍 XPay是专为个人站长打造的聚合免签系统,拥有卓越的性能和丰富的功能。采用全新轻量化的界面UI,让您可以更加方便快捷地解决 知识付费和运营赞助的难题。同时,它基于高性能的Thin…

算法练习:前缀和

目录 1. 一维前缀和2. 二维前缀和3. 寻找数组中心下标4. 除自身以外数组的乘积5. !和为k的子数字6. !和可被k整除的子数组7. !连续数组8. 矩阵区域和 1. 一维前缀和 题目信息: 题目链接: 一维前缀和思路:求前缀和数组,sum dp[r] …

预应力锚杆测力计安装埋设

锚杆测力计用于观测预应力锚杆预应力的形成与变化。当前,预应力锚杆广泛地应用于岩土工程的锚固结构中,通过安装测力计观测锚杆,可以了解锚固力的形成与变化,从而保证监测工程的质量与安全。测力计的安装包括安装测力计和观测锚杆…

【LeetCode热题100】 226. 翻转二叉树(二叉树)

一.题目要求 给你一棵二叉树的根节点 root ,翻转这棵二叉树,并返回其根节点。 二.题目难度 简单 三.输入样例 示例 1: 输入:root [4,2,7,1,3,6,9] 输出:[4,7,2,9,6,3,1] 示例 2: 输入:…

餐饮店引流活动方案与最佳营销方案揭秘

想开实体店或正在创业的朋友们,大家好!我是一名资深的实体店创业者,本人经营鲜奶吧5年时间,做的是社区店,今天我将分享一些餐饮店引流活动和营销方案的干货,希望能给大家带来一些启发和帮助。 一、引流活动…

【人工智能】英文学习材料02(每日一句)

🌻个人主页:相洋同学 🥇学习在于行动、总结和坚持,共勉! 目录 Supervised Learning(监督学习) Unsupervised Learning(无监督学习 ) Semi-supervised Learning&#…

【视频图像取证篇】模糊图像增强技术之色彩空间类滤波器场景应用小结

【视频图像取证篇】模糊图像增强技术之色彩空间类滤波器场景应用小结 模糊图像增强技术之色彩空间HSI滤波器—【蘇小沐】 (一)色彩空间滤波器 1、HSI滤波器 HSI(色调、饱和度和强度)滤镜用于将彩色图像转换为 HSI 图像。这意味…

当贝X5 Ultra坚果N1S Ultra哪个好?2024年旗舰投影仪哪家强

家用投影仪在目前年轻用户新家装修的娱乐选择上,有着越来越大的占比。不过虽然投影仪的体验已经逐渐弯道超越传统电视,画面和沉浸感已经抹去了曾经的一些小问题;但仍然有很多雷区和选购的迷惑,以致于在同价位往往陷入不知道哪款更…

展厅设计提高人气的妙招

1、清晰的标识 展厅门口的标识是消费者第一眼能了解到的信息,所以一定要做到简单清楚,在开设专卖店时,就要将标识做到清晰醒目,方便客户寻找。 2、舒适的灯光 灯光是展厅装修中最为重要的一部分,灯光太亮会让人感觉不舒…

基于spring boot的钢材销售管理系统的设计与实现

钢材销售管理系统 摘 要 本系统为用户而设计制作钢材销售管理系统,旨在实现钢材销售智能化、现代化管理。本钢材销售管理自动化系统的开发和研制的最终目的是将钢材销售的运作模式从手工记录数据转变为网络信息查询管理,从而为现代管理人员的使用提供更…