JVM内存回收算法

4351fdce7b184a8996b3c90cb2b3225d.jpg1.1 引用计数法

 

每个对象创建的时候,会分配一个引用计数器,当这个对象被引用的时候计数器就加1,当不被引用或者引用失效的时候计数器就会减1。任何时候,对象的引用计数器值为0就说明这个对象不被使用了,就认为是“垃圾”,可以被GC处理掉。

 

【优点】算法实现简单。

【缺点】不能解决对象之间循环引用的问题。有垃圾对象不能被正确识别,这对垃圾回收来说是很致命的,所以GC并没有使用这种搜索算法。

1.2 根搜索算法

以一些特定的对象作为基础原始对象,或者称作“根”,不断往下搜索,到达某一个对象的路径称为引用链。

如果一个对象和根对象之间有引用链,即根对象到这个对象是可到达的,则这个对象是活着的,不是垃圾,还不能回收。例如,假设有根对象O,O引用了A对象,同时A对象引用了B对象,B对象又引用了C对象,那么对象C和根对象O之间的路径的可达的,C对象就不能当做垃圾对象。引用链为O->A->B->C。

反之,如果一个对象和根对象之间没有引用链,根对象到这个对象的路径是不可达的,那么这个对象就是可回收的垃圾对象。

 

 

【优点】可找到所以得垃圾对象,并且完美解决对象之间循环引用的问题。

【缺点】不可避免地要遍历全局所有对象,导致搜索效率不高。

根搜索算法是现在GC使用的搜索算法。

 

可以当做GC roots的对象有以下几种:

 

虚拟机栈中的引用的对象。(java栈的栈帧本地变量表)

 

方法区中的类静态属性引用的对象。

 

方法区中的常量引用的对象。(声明为final的常量对象)

 

本地方法栈中JNI的引用的对象。(本地方法栈的栈帧本地变量表)

 

下面是从网上找来的图,将就看看:GC ROOTS就是跟对象节点,蓝色的是可达的引用链,引用链上的对象是活着的,不能被当做垃圾对象回收。相反暗灰色的路径表示不可达的路径,这些对象将会被回收。每个圈圈里面的数字,表示其被引用的次数,没错,就是上面说到的引用计数法的计数值。跟搜索算法示例图

 

2.GC算法

这里讨论的是oracle的Hotspot VM常见的垃圾回收算法。使用的搜索算法都是基于根搜索算法实现的。

 

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

该算法分两步执行:

 

1) 标记Mark:从GC ROOTS开始,遍历堆内存区域的所有根对象,对在引用链上的对象都进行标记。这样下来,如果是存活的对象就会被做了标记,反之如果是垃圾对象,则没做有标记。GC很容易根据有没有被做标记就完成了垃圾对象回收。

 

2) 清除Sweep:遍历堆中的所有的对象(标记阶段遍历的是所有根节点),找到未被标记的对象,直接回收所占的内存,释放空间。

 

评价:

 

【优点】没有产生额外的内存空间消耗,内存利用率高。

【缺点】效率低,清除阶段要遍历所有的对象;回收的垃圾对象是在各个角落的,直接回收垃圾对象,导致存在不连续的内存空间,产生内存碎片。

标记-清除算法操作的对象是【垃圾对象】,对于活着的对象(被标记的对象),它则直接不理睬。

 

2.2 复制算法(Copying)

复制算法把内存区间一分为二,有对象存在的一半区间称为“活动区间”,没有对象存在处于空闲状态的空间则为“空闲区间”。

当内存空间不足时触发GC,先采用根搜索算法标记对象,然后把活着的对象全部复制到另一半空闲区间上,复制算法的“复制”就来自这一操作。复制到另一半区间的时候,严格按照内存地址依次排列要存放的对象,然后一次性回收垃圾对象。

这样原来的空闲区间在GC后就变成活动区间,而且内存顺序齐整美观。原来的活动区间在GC后就变成了完全空的空闲区间,等待下一次GC把活的对象被copy进来。

 

评价:

 

【优点】GC后的内存齐整,不产生内存碎片。

【缺点】GC要使用两倍的内存,或者说导致堆只能使用被分配到的内存的一半,这个算法对空间要求太高!如果存活的对象较多,则意味着要复制很多对象并且要维护大量对象的内存地址,所以存活的对象数量不能太多,否则效率也会很低。

复制算法复制移动的对象是【活着的对象】,对于垃圾对象(不被标记的对象)则直接回收。

 

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

这个算法则是对上面两个算法的综合结果。也分为两个阶段:

 

1)标记:这个阶段和标记-清除Mark-Sweep算法一样,遍历GC ROOTS并标记存活的对象。

 

2)整理:移动所有活着的对象到内存区域的一侧(具体在哪一侧则由GC实现),严格按照内存地址次序依次排列活着的对象,然后将最后一个活着的对象地址以后的空间全部回收。

 

评价:

 

【优点】内存空间利用率高,消除了复制算法内存减半的情况;GC后不会产生内存碎片。

 

【缺点】需要遍历标记活着的对象,效率较低;复制移动对象后,还要维护这些活着对象的引用地址列表。

 

2.4 分代回收算法(Generational Collecting)

分代回收算法就是现在JVM使用的GC回收算法。

 

2.4.1简要说明

1)先来看看简单化后的堆的内存结构:

 

Java堆 = 年老代 + 年轻代

(空间大小比例一般是3:1)

 

年轻代 = Eden区 + From Space区 + To Space区

(空间大小比例一般是8:1:1)

2)按照对象存活时间长短,我们可以把对象简单分为三类:

 

短命对象:存活时间较短的对象,如中间变量对象、临时对象、循环体创建的对象等。这也是产生最多数量的对象,GC回收的关注重点。

 

长命对象:存活时间较长的对象,如单例模式产生的单例对象、数据库连接对象、缓存对象等。

 

长生对象:一旦创建则一直存活,几乎不死的对象。

 

3)对象分配区域

短命对象存在于年轻代,长命对象存在于年老代,而长生对象则存在于方法区中。

由于GC的主要内存区域是堆,所以GC的对象主要就是短命对象和长命对象这类寿命“有限”的对象。

 

2.4.2 分代回收的GC类型

针对HotSpot VM的的GC其实准确分类只有两大种:

 

1)Partial GC:部分回收模式

 

Young GC:只收集young gen的GC。和Minor GC一样。

Old GC:只收集old gen的GC。只有CMS的concurrent - collection是这个模式

Mixed GC:收集整个young gen以及部分old gen的GC。只有G1有这个模式

2)Full GC:收集整个堆,包括young gen、old gen,还有永久代perm gen(如果存在的话)等所有部分的模式。同Major GC。

 

3)触发时机

HotSpot VM的串行GC的触发条件是:

young GC:当young gen中的eden区分配满的时候触发。

 

full GC:当准备要触发一次young GC时,如果发现统计数据说之前young GC的平均晋升大小比目前old gen剩余的空间大,则不会触发young GC而是转为触发full GC;或者,如果有perm gen的话,要在perm gen分配空间但已经没有足够空间时,也要触发一次full GC;或者System.gc()、heap dump带GC,默认也是触发full GC。

 

并发GC的触发条件就不太一样。以CMS GC为例,它主要是定时去检查old gen的使用量,当使用量超过了触发比例就会启动一次CMS GC,对old gen做并发收集。

 

2.4.3 年轻代GC过程

当需要在堆中创建一个新的对象,而年轻代内存不足时触发一次GC,在年轻代触发的GC称为普通GC,Minor GC。注意到年轻代中的对象都是存活时间较短的对象,所以适合使用复制算法。这里肯定不会使用两倍的内存来实现复制算法了,牛人们是这样解决的,把年轻代内存组成是80%的Eden、10%的From Space和10%的To Space,然后在这些内存区域直接进行复制。

 

刚开始创建的对象是在Eden中,此时Eden中有对象,而两个survivor区没有对象,都是空闲区间。第一次Minor GC后,存活的对象被放到其中一个survivor,Eden中的内存空间直接被回收。在下一次GC到来时,Eden和一个survivor中又创建满了对象,这个时候GC清除的就是Eden和这个放满对象的survivor组成的大区域(占90%),Minor GC使用复制算法把活的对象复制到另一个空闲的survivor区间,然后直接回收之前90%的内存。周而复始。始终会有一个10%空闲的survivor区间,作为下一次Minor GC存放对象的准备空间。

 

要完成上面的算法,每次Minor GC过程都要满足:

存活的对象大小都不能超过survivor那10%的内存空间,不然就没有空间复制剩下的对象了。但是,万一超过了呢?前面我们提到过年老代,对,就是把这些大对象放到年老代。

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

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

相关文章

从8.8到9.9,涨价的库迪还能守住牌局吗?

作者 | 辰纹 来源 | 洞见新研社 历经超半年的9.9元活动后,瑞幸不仅牢牢守稳盈利态势,还一举创造了新的神话——中国地区年收入首超星巴克。 根据瑞幸咖啡发布的截至12月31日的2023年第四季度及全年财报。第四季度,瑞幸咖啡净营收为70.6亿元…

【VTKExamples::PolyData】第四十一期 PointLocator

很高兴在雪易的CSDN遇见你 VTK技术爱好者 QQ:870202403 前言 本文分享VTK样例PointLocator,并解析接口vtkPointLocator,希望对各位小伙伴有所帮助! 感谢各位小伙伴的点赞+关注,小易会继续努力分享,一起进步! 你的点赞就是我的动力(^U^)ノ~YO 1. PointLocator …

ubuntu16.04安装Mysql8.0.25

更换数据源(阿里云) sudo cp /etc/apt/sources.list /etc/apt/sources.list.bak sudo vi /etc/apt/sources.listdeb http://mirrors.aliyun.com/ubuntu/ xenial main multiverse restricted universe deb http://mirrors.aliyun.com/ubuntu/ xenial-backports main multiverse…

第四十三天| 1049. 最后一块石头的重量 II、494. 目标和、474.一和零

01背包问题 Leetcode 1049. 最后一块石头的重量 II 题目链接:1049 最后一块石头的重量 II 题干:有一堆石头,用整数数组 stones 表示。其中 stones[i] 表示第 i 块石头的重量。 每一回合,从中选出任意两块石头,然后将…

Harbor高可用(haproxy和keepalived)

Harbor高可用(haproxy和keepalived) 文章目录 Harbor高可用(haproxy和keepalived)1.Harbor高可用集群部署架构1.1 主机初始化1.1.1 设置网卡名和ip地址1.1.2 设置主机名1.1.3 配置镜像源1.1.4 关闭防火墙1.1.5 禁用SELinux1.1.6 设…

Typora快捷键设置详细教程(内附每个步骤详细截图)

😎 作者介绍:我是程序员洲洲,一个热爱写作的非著名程序员。CSDN全栈优质领域创作者、华为云博客社区云享专家、阿里云博客社区专家博主、前后端开发、人工智能研究生。公粽号:程序员洲洲。 🎈 本文专栏:本文…

探秘Python的Pipeline魔法

前些天发现了一个巨牛的人工智能学习网站,通俗易懂,风趣幽默,忍不住分享一下给大家。点击跳转到网站AI学习网站。 目录 前言 什么是Pipeline? Pipeline的基本用法 Pipeline的高级用法 1. 动态调参 2. 并行处理 3. 多输出 …

第四十七回 一丈青单捉王矮虎 宋公明二打祝家庄-强大而灵活的python装饰器

四面全是埋伏,宋江和众人一直绕圈跑不出去。正在慌乱之时,石秀及时赶到,教大家碰到白杨树就转弯走。走了一段时间,发现围的人越来越多,原来祝家庄以灯笼指挥号令。花荣一箭射下来红灯龙,伏兵自己就乱起来了…

教你快速认识Java中的继承和多态

目录 继承 继承的概念 继承的语法 父类成员访问 在子类方法中或者通过子类对象访问父类成员变量时: 在子类方法中或者通过子类对象访问父类成员方法时: super关键字 子类构造方法: 代码块执行顺序: 多态 多态的实现条件 重写 重…

NFTScan NFT API 在 Web3 钱包追踪器上的开发应用

Web3 钱包追踪器是通过整合区块链数据 API,为加密资产投资者提供全面的钱包分析和追踪工具。用户可以利用钱包追踪器跟踪特定钱包地址的资产总额和交易情况,分析历史交易发现交易趋势,设置资产价格警报,生成钱包报告,同…

应用层DDoS防护:理解、必要性与实现策略

一、应用层简介 应用层,也称作第七层,是OSI(开放系统互联)模型中的最高层。在这一层,数据以特定的应用程序协议格式进行传输,如HTTP、FTP、SMTP等。应用层的主要职责是为用户提供网络服务,如文…

kotlin单例模式,4年小Android的心路历程

一、Java基础 我知道大家一定有很久都没有注意到这个点了,平时的工作应该也很少涉及到这些底层知识吧,但是这些东西很重要。如果是想要跳槽加薪或者是应对即将到来的面试,这些都是不可忽视的知识。 在这一点里,需要重视的点有&am…

linux操作docker

docker地址 官方地址 centos7安装docker 卸载旧版本docker sudo //在前面表示以管理员权限操作yum remove docker \docker-client \docker-client-latest \docker-common \docker-latest \docker-latest-logrotate \docker-logrotate \docker-engine安装docker //安装所需资…

每日五道java面试题之mysql数据库篇(一)

目录: 第一题. 为什么要使用数据库?第二题. 数据库三大范式是什么?第三题. mysql有关权限的表都有哪几个?第四题. MySQL的binlog有有几种录入格式?分别有什么区别?第五题. MySQL存储引擎MyISAM与InnoDB区别 第一题. 为什么要使用数据库? …

获取当前数据 上下移动

点击按钮 上下移动 当前数据 代码 // 出国境管理 登记备案人员列表 <template><a-row><a-col span"24"><a-card :class"style[a-table-wrapper]"><!-- 出国境 登记备案人员列表 --><a-table:rowKey"records >…

【零基础SRC】成为漏洞赏金猎人的第一课:加入玲珑安全漏洞挖掘班。

我们是谁 你是否对漏洞挖掘充满好奇&#xff1f;零基础或有基础但想更进一步&#xff1f;想赚取可观的漏洞赏金让自己有更大的自由度&#xff1f; 那么&#xff0c;不妨了解下我们《玲珑安全团队》。 玲珑安全团队&#xff0c;拥有多名实力讲师&#xff0c;均就职于互联网头…

记录 android studio 通过安装NDK 编译C文件,得到需要的so文件

只怪自己太健忘&#xff0c;每次网上查了一圈&#xff0c;搞定后&#xff0c;再遇到又发现不会操作了&#xff0c;特此记下 不废话直接上步骤 &#xff08;1&#xff09; 进入AS的settinging如下界面 &#xff08;2&#xff09;选中图片箭头两个文件 进行下载 &#xff08;…

【JVM】聊聊常见的JVM排查工具

JDK工具包 jps 虚拟机进程状况工具 jps是虚拟机进程状况工具&#xff0c;列出正在运行的虚拟机进程&#xff0c;使用 Windows 的任务管理器或 UNIX 的 ps 命令也可以查询&#xff0c;但如果同时启动多个进程&#xff0c;必须依赖 jps。jps -l 显示类名 jps :列出Java程序进程…

Chrome插件 | WEB 网页数据采集和爬虫程序

无边无形的互联网遍地是数据&#xff0c;品类丰富、格式繁多&#xff0c;包罗万象。数据采集&#xff0c;或说抓取&#xff0c;就是把分散各处的内容&#xff0c;通过各种方式汇聚一堂&#xff0c;是个有讲究要思考的体力活。君子爱数&#xff0c;取之有道&#xff0c;得注意遵…

raw数据噪声模型和标定

噪声在ISP中去得越早越好&#xff0c;因为噪声在最开始成像的过程中就引入了&#xff0c;之后只会不断放大。具体而言&#xff0c;噪声产生的位置就是上图中绿色框的区域。 泊松分布 从二项分布中推导出来&#xff0c;描述一段时间内的次数&#xff0c;只需要知道”比率“&am…