垃圾回收机制及算法

文章目录

    • 概要
    • 对象存活判断
      • 引用计数算法
      • 可达性分析算法
      • 对象是否存活
      • 各种引用
    • 垃圾收集算法
      • 分代收集理论
      • 复制算法
      • 标记清除算法
      • 标记-整理算法

概要

垃圾收集(Garbage Collection, 下文简称GC),其优缺点如下:
优点:

  • 不需要考虑内存管理,
  • 可以有效的防止内存泄漏,有效的利用可使用的内存,

缺点:

  • java开发人员不了解自动内存管理, 内存管理就像一个黑匣子,过度依赖就会降低我们解决内存溢出/内存泄漏等问题的能力。

对象存活判断

引用计数算法

引用计数算法可以这样实现:给每个创建的对象添加一个引用计数器,每当此对象被某个地方引用时,计数值+1,引用失效时-1,所以当计数值为0时表示对象已经不能被使用。引用计数算法大多数情况下是个比较不错的算法,简单直接,也有一些著名的应用案例但是对于Java虚拟机来说,并不是一个好的选择,因为它很难解决对象直接相互循环引用的问题。

优点:
实现简单,执行效率高,很好的和程序交织。
缺点:
无法检测出循环引用。

可达性分析算法

在主流的商用程序语言如Java、C#等的主流实现中,都是通过可达性分析(Reachability Analysis)来判断对象是否存活的。此算法的基本思路就是通过一系列的“GC Roots”的对象作为起始点,从起始点开始向下搜索到对象的路径。搜索所经过的路径称为引用链(Reference Chain),当一个对象到任何GC Roots都没有引用链时,则表明对象“不可达”,即该对象是不可用的。

在这里插入图片描述

在Java语言中,可作为GC Roots的对象包括下面几种:

  • 栈帧中的局部变量表中的reference引用所引用的对象
  • 方法区中static静态引用的对象
  • 方法区中final常量引用的对象
  • 本地方法栈中JNI(Native方法)引用的对象
  • Java虚拟机内部的引用, 如基本数据类型对应的Class对象, 一些常驻的异常对象(比如 NullPointExcepiton、
    OutOfMemoryError) 等, 还有系统类加载器。
  • 所有被同步锁(synchronized关键字) 持有的对象
  • 反映Java虚拟机内部情况的JMXBean、 JVMTI中注册的回调、 本地代码缓存等

在这里插入图片描述

对象是否存活

finalize()方法最终判定对象是否存活:

即使在可达性分析算法中判定为不可达的对象, 也不是“非死不可”的, 这时候它们暂时还处于“缓刑”阶段, 要真
正宣告一个对象死亡, 至少要经历两次标记过程:

第一次标记:
如果对象在进行可达性分析后发现没有与GC Roots相连接的引用链, 那它将会被第一次标记, 随后进行一次筛选, 筛选的条件是此对象是否有必要执行finalize()方法。
没有必要:
假如对象没有覆盖finalize()方法, 或者finalize()方法已经被虚拟机调用过, 那么虚拟机将这两种情况都视为“没有必要执行”。
有必要:

如果这个对象被判定为确有必要执行finalize()方法, 那么该对象将会被放置在一个名为F-Queue的 队列之中, 并在
稍后由一条由虚拟机自动建立的、 低调度优先级的Finalizer线程去执行它们的finalize() 方法。 finalize()方法是对 象
逃脱死亡命运的最后一次机会, 稍后收集器将对F-Queue中的对象进行第二次小规模的标记, 如果对 象要在
finalize()中成功拯救自己——只要重新与引用链上的任何一个对象建立关联即可, 譬如把自己 (this关键字) 赋值
给某个类变量或者对象的成员变量, 那在第二次标记时它将被移出“即将回收”的集 合; 如果对象这时候还没有逃
脱, 那基本上它就真的要被回收了。

在这里插入图片描述

Finalizer线程去执行它们的finalize() 方法, 这里所说的“执行”是指虚拟机会触发这个方法开始运行, 但并不承诺一定会等待它运行结束。 这样做的原因是, 如果某个对象的finalize()方法执行缓慢, 或者更极端地发生了死循环, 将很可能导 致F-Queue队列中的其他对象永久处于等待, 甚至导致整个内存回收子系统的崩溃。

各种引用

在JDK1.2之后,Java对引用的概念做了扩充,将引用分为 强引用(Strong Reference) 、 软引用(Soft Reference) 、 弱引用(Weak Reference) 和 虚引用(Phantom Reference) 四种,这四种引用的强度依次递减。

  • 强引用:是使用最普遍的引用。如果一个对象具有强引用,那垃圾回收器绝不会回收它。当内存空间不足,Java虚拟
    机宁愿抛出OutOfMemoryError错误,使程序异常终止,也不会靠随意回收具有强引用的对象来解决内存不足的问
    题。 ps:强引用其实也就是我们平时A a = new A()这个意思。

  • 软引用: 如果一个对象只具有软引用,则内存空间足够,垃圾回收器就不会回收它;如果内存空间不足了,就会回收这些对象的内存。只要垃圾回收器没有回收它,该对象就可以被程序使用。 软引用可以和一个引用队列
    (ReferenceQueue)联合使用,如果软引用所引用的对象被垃圾回收器回收,Java虚拟机就会把这个软引用加入到与之关联的引用队列中。

  • 弱引用:用来描述那些非必须对象。 当垃圾收集器开始工作, 无论当前内存是否足够, 都会回收掉只被弱引用关联的对象。 在JDK 1.2版之后提供了WeakReference类来实现弱引用。 弱引用可以和一个引用队列(ReferenceQueue)联合使用,如果弱引用所引用的对象被垃圾回收,Java虚拟机就会把这个弱引用加入到与之关联的引用队列中.

  • 虚引用:一个对象仅持有虚引用,在任何时候都可能被垃圾回收器回收。虚引用主要用来跟踪对象被垃圾回收器回收的活动
    虚引用与软引用和弱引用的一个区别在于:
    1、引用必须和引用队列 (ReferenceQueue)联合使用。
    2、当垃圾回收器准备回收一个对象时,如果发现它还有虚引用,就会在回收对象的内存之前,把这个虚引用加入到
    与之 关联的引用队列中。

垃圾收集算法

分代收集理论

当前商业虚拟机的垃圾回收器,大多遵循“分代收集”的理论来进行设计,这个理论大体上是这么描述的:

  • 绝大部分的对象都是朝生夕死。
  • 熬过多次垃圾回收的对象就越难回收

根据以上两个理论,朝生夕死的对象放一个区域,难回收的对象放另外一个区域,这个就构成了新生代和老年代,并且不同的分代采用的回收算法不一样。

在这里插入图片描述
同时对于GC的叫法,大体有这么几种:
1、新生代回收( Minor GC/Young GC ):指的是进行新生代的回收。
2、老年代回收( Major GC/Old GC ):指的是进行老年代的回收。目前只有 CMS 垃圾回收器会有这个单独的回收老年代的行为。( Major GC 定义相对没有那么明确,有说指是老年代,有的说是做整个堆的收集,没有固定的说法,有时候 Major GC 和 Full GC 大致是等价的)
3、整堆回收( Full GC ):定义相对明确,收集整个 Java 堆和方法区(注意包含方法区)

复制算法

原始的复制算法(Copying)是这样的:

  • 将内存按容量划分为大小相等的两块,每次只使用其中的一块。
  • 当其中一块内存用完了,就将还存活着的对象复制到另外一块上面,然后再把已使用过的内存空间一次清理掉。

在这里插入图片描述

优点:

  • 实现简单,运行高效,
  • 每次都是对整个半区进行内存回收,内存分配时也就不用考虑内存碎片等复杂情况,只要按顺序分配内存即可

缺点:

  • 内存的使用率缩小为原来的一半。
  • 内存移动是必须实打实的移动(复制),所以对应的引用(直接指针)需要调整。

适用场景:
复制回收算法适合于新生代,因为大部分对象朝生夕死,那么复制过去的对象比较少,效率自然就高,另外一半的一次性清理是很快的。

像 hotspot 这样的虚拟机大都对原生的复制算法进行了改进,因为它对内存空间的利用率不高,而且专门研究表明,新生代中的对象 98% 是“朝生夕死”的,所以并不需要按照 1:1 的比例来划分内存空间,所以改进后的复制算法策略是:

1、将新生代划分为一块较大的 Eden 区和两块较小的 Survivor 空间(你可以叫做 From 或者 To ) , HotSpot 虚拟机默认 Eden 和 Survivor 的大小比例是 8:1 。
2、每次使用 Eden 和其中一块 Survivor ,当回收时,将 Eden 和Survivor 中还存活着的对象一次性地复制到另外一块 Survivor 空间上,最后清理掉 Eden 和刚才用过的 Survivor 空间。

在这样的算法下,
1、每次新生代中可用内存空间为整个新生代容量的 90%(80%+10%),只有 10%的内存会被 “浪费”
2、当然,98%的对象可回收只是一般场景下的数据,我们没有办法保证每次回收都只有不多于 10%的对象存活,当 Survivor 空间不够用时,需要依赖其他内存(老年代)进行分配担保( Handle Promotion )。

标记清除算法

标记-清除(Mark-Sweep)算法分为“标记”和“清除”两个阶段:

  • 首先扫描所有对象标记出需要回收的对象
  • 在标记完成后扫描并回收所有被标记的对象,故需要两次扫描

在这里插入图片描述
注意:
1、回收效率略低,如果大部分对象是朝生夕死,那么回收效率降低,因为需要大量标记对象和回收对象,对比复制回收效率要低,所以该算法不适合新生代。
2、它的主要问题是在标记清除之后会产生大量不连续的内存碎片,空间碎片太多可能会导致以后在程序运行过程中需要分配较大对象时,无法找到足够的连续内存而不得不提前触发另一次垃圾回收动作。
3、标记清除算法适用于老年代。

标记-整理算法

标记-整理(Mark-Compact)算法逻辑如下:
1、首先标记出所有需要回收的对象,
2、在标记完成后,后续步骤不是直接对可回收对象进行清理,而是让所有存活的对象都向一端移动,
3、然后直接清理掉端边界以外的内存。

在这里插入图片描述

注意:
1、标记整理需要扫描两遍
2、标记整理与标记清除算法的区别主要在于对象的移动。对象移动不单单会加重系统负担,同时需要全程暂停用户线程才能进行,同时所有引用对象的地方都需要更新(直接指针需要调整)。
3、标记整理算法不会产生内存碎片,但是效率偏低。
4、标记整理算法适用于老年代。

所以看到,老年代采用的标记整理算法与标记清除算法,各有优点,各有缺点。

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

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

相关文章

Nature Communications | 柔性半导体器件的大规模集成(柔性半导体器件/柔性电子)

韩国中央大学Sung Kyu Park、 韩国成均馆大学Jong-Woong Kim和Yong-Hoon Kim团队,在《Nature Communications》上发布了一篇题为“Full integration of highly stretchable inorganic transistors and circuits within molecular-tailored elastic substrates on a large scal…

OZONBIGSELL分析产品工具,OZON平台数据分析

在当今的数字化时代,电商平台的竞争日趋激烈,数据成为了企业决策的重要支撑。OZON作为俄罗斯领先的电商平台,其背后蕴含的海量数据对于卖家而言,既是挑战也是机遇。接下来看看OZONBIGSELL这一分析产品工具,以及如何利用…

等保2.0看这一篇就够了

一、等级保护介绍 1.1什么是等级保护 网络安全等级保护是指对国家重要信息、法人和其他组织及公民的专有信息以及信息和存储、传输、处理这些信息的信息系统分等级实行安全保护,对信息系统中使用的信息安全产品实行按等级管理,对信息系统中发生的信息安…

ROS | C++和python实现发布结点和订阅结点

发布者结点: 代码实现: python: C: C和Python发布结点的差异: python: 发布结点pub 大管家rospy调用publisher函数发布话题 (话题,类型,话题长度) C: 先定义一个大管家:NodeHandle 然后大管家发布话题…

C# NetworkStream 流的详解与示例

文章目录 一、NetworkStream类的基本概念1.1 NetworkStream类概述1.2 NetworkStream类属性1.3 NetworkStream类方法 二、NetworkStream的连接方式三、NetworkStream的传输模式四、NetworkStream类示例服务器端代码:客户端代码: 五、总结 在C#中&#xff…

VS Code添加高亮缩进功能

当代码缩进层次较多时,为了视觉上容易识别,一般希望可以多个缩进以不同颜色进行高亮显示, VS Code 中 indent-rainbow 插件可以实现这个功能。

python列表生成式的魅力:轻松创建新列表

新书上架~👇全国包邮奥~ python实用小工具开发教程http://pythontoolsteach.com/3 欢迎关注我👆,收藏下次不迷路┗|`O′|┛ 嗷~~ 目录 1. 列表生成式的基本结构 2. 列表生成式的进阶应用 3. 结合其他结构使用列表生成式 1. 列表…

HTML静态网页成品作业(HTML+CSS)——利物浦足球俱乐部介绍网页设计制作(5个页面)

🎉不定期分享源码,关注不丢失哦 文章目录 一、作品介绍二、作品演示三、代码目录四、网站代码HTML部分代码 五、源码获取 一、作品介绍 🏷️本套采用HTMLCSS,共有5个页面。 二、作品演示 三、代码目录 四、网站代码 HTML部分代…

校园招新之获取进QQ群但未报名人员

校园的社团、实验室招新一般由是校领导会发一个QQ通知,让各个班的同学们进一个招新群。 群里面会有负责人提示大家报名,但是群成员不总是都会报名,我们需要的就是,找到那些,已经进群,但是没有报名的同学&am…

ELK 日志监控平台(一)- 快速搭建

文章目录 ELK 日志监控平台(一)- 快速搭建1.ELK 简介2.Elasticsearch安装部署3.Logstash安装部署4.Kibana安装部署5.日志收集DEMO5.1.创建SpringBoot应用依赖导入日志配置文件 logback.xml启动类目录结构启动项目 5.2.创建Logstash配置文件5.3.重新启动L…

当HR问你是否单身时,该怎么回答?

知识星球(星球名:芯片制造与封测技术社区,星球号:63559049)里的学员问:我是晶圆厂厂务工程师,最近在面试新工作,但是几乎每家HR都会问我同一个问题:你结婚没有&#xff1…

解密Spring Boot Starter与自动配置:探秘神奇的背后

starter可以理解为Spring Boot中的一站式集成启动器,包含了一系列可以集成到应用中的依赖项,可以快递集成spring组件及其框架,而不需要到处找示例代码。 一、为什么要用starter? 在springboot还没有出来之前,我们使用…

wps使用(解决毕业论文)

目录自动生成 页码自动生成 一部分使用I II III IV 格式,一部分使用1,2,3,4 格式 先设置全部文章为I II III IV 格式,然后再需要的地方再设置1,2,3,4 格式 一键设置中文、英文、数…

2024年全国大学生电工数学建模竞赛B题解析 | 数据处理 代码 论文分享

B 题:大学生平衡膳食食谱的优化设计及评价 1 数据预处理2 问题一2.1 问题1.12.1.1 评价体系的构建2.1.2 指标计算2.1.3 指标计算结果2.1.4 基于层次分析法的膳食营养评价模型2.1.5 评价模型的求解 2.2 问题1.22.2.1 食物与成分间拓扑关系的构建2.2.2 微调模型的建立…

【SpringBoot】整合百度文字识别

流程图 一、前期准备 1.1 打开百度智能云官网找到管理中心创建应用 全选文字识别 1.2 保存好AppId、API Key和Secret Key 1.3 找到通用场景文字识别,立即使用 1.4 根据自己需要,选择要开通的项目 二、代码编写 以通用文字识别(高精度版&am…

蚁小二:又一款高效自媒体工具,免费用户可发5个账号

其实自媒体的群发工具有几个,除了前几天介绍的融媒宝还有蚁小二等。因为融媒宝免费用户只能添加5个账号,所以不够用的朋友可以再下载蚁小二使用,这样就有10个账号可以发布了: 蚁小二简介 蚁小二是由长沙草儿绽放科技有限公司自主…

mysql - 索引原理

mysql索引原理 文中的查询, 以该表结构为例 CREATE TABLE user (id int NOT NULL COMMENT id,name varchar(255) COLLATE utf8mb4_bin NOT NULL COMMENT 姓名,age int NOT NULL COMMENT 年龄,sex tinyint(1) NOT NULL COMMENT 性别,phone varchar(255) CHARACTER SET utf8mb4…

设计模式9——适配器模式

写文章的初心主要是用来帮助自己快速的回忆这个模式该怎么用,主要是下面的UML图可以起到大作用,在你学习过一遍以后可能会遗忘,忘记了不要紧,只要看一眼UML图就能想起来了。同时也请大家多多指教。 适配器模式(Adapte…

酷开科技以内容为契机,酷开系统向消费者需求的深度挖掘迈进一步

酷开系统还拥有强大的内容资源和推荐算法,能够根据消费者的兴趣爱好为其提供个性化的推荐服务。无论是电影、电视剧、综艺节目,还是新闻、体育、娱乐资讯,酷开系统都能帮助大家快速找到感兴趣的内容,并且通过智能推荐算法不断优化…

(南京观海微电子)——TFT LCM的作用

VCOM介绍 VCOM是液晶分子偏转的参考电压 ,要求要稳定,对液晶显示有直接影响,具体的屏不同的话 也是不同的。 电压的具体值是根据输入的数据以及Vcom电压大小来确定的,用来显示各种不同灰阶,也就是实现彩色显示GAMMA简…