2023.9.2 关于 JVM 垃圾回收机制(GC)

目录

为什么要有垃圾回收机制?

STW(Stop The World)问题

垃圾回收机制主要回收哪个内存区域?

垃圾对象判断算法

引用计数算法

可达性分析算法

垃圾对象回收算法

标记清除算法

复制算法

标记整理算法

分代算法


为什么要有垃圾回收机制?

  • 自动内存管理:垃圾回收机制使得内存的分配释放过程自动化,开发者不需要手动跟踪和释放不再使用的内存,减轻了开发工作量
  • 避免内存泄漏:内存泄漏指程序中分配的内存空间无法被回收和重用,导致内存资源的浪费和耗尽,而垃圾回收机制可以自动检测和回收这些不再使用的内存,从而避免内存泄漏
  • 解决内存碎片化:内存碎片化指内存空间的可用部分被分割成多个小块,无法满足大块内存的分配请求,垃圾回收机制可以通过整理和压缩内存空间,将分散的小块内存合并成更大的可用内存块,从而减少了内存碎片化问题
  • 提高程序性能:垃圾回收机制虽然会引入额外的性能开销,但相比手动内存管理,它通过智能算法来判断哪些对象是可回收的,从而避免了不必要的内存分配和释放操作,可以更高效的管理内存资源,从而提高程序的整体性能
  • 内存安全:垃圾回收机制可以检测和处理悬空引用和野指针等内存安全问题,它可以识别不再被引用的对象,并再必要时进行回收,避免了程序访问无效内存的风险

STW(Stop The World)问题

垃圾回收机制最大的问题就是会引入额外的 空间+时间 开销

  • 空间上:额外消耗 CPU 和内存资源
  • 时间上:STW 问题

STW 问题 指程序运行到需要用 GC 释放内存的时候,可能会导致程序的响应变慢,反应到用户便可能存在明显的卡顿


总结:

总体来说,JVM 垃圾回收机制是 Java 语言的重要特性,它为开发者提供了方便、安全、高效的内存管理方式,减少了内存相关的错误和问题,其开发效率是大于运行效率的!

垃圾回收机制主要回收哪个内存区域?

  • GC 主要是针对 进行释放回收
  • GC 以 对象为基本单位 进行回收

垃圾对象判断算法

引用计数算法

  • 引用计数算法被 Python、PHP 所采用,非 Java 所采用的算法

具体思路:

  • 每个对象都有一个关联的计数器,用于记录当前对象被其他对象引用的次数
  • 每多一个引用指向该对象,计数器就 +1
  • 每少一个引用指向该对象,计数器就 -1
  • 当对象的计数器为 0 时,将被视为垃圾对象,可被垃圾回收器回收 

缺点:

  • 内存空间利用率低:对于小对象来说,可能一个计数器的所占内存比其本身还大
  • 存在循环引用的问题


可达性分析算法

  • 可达性分析算法为 Java 所采用的垃圾对象​​​​判断算法

具体思路:

  • 根集确定(GC Roots):垃圾回收器首先要确定根集的内容,其根集可为 栈中引用的对象方法区中类静态属性引用对象方法区中常量引用的对象本地方法栈中 Native 方法引用的对象

  • 根集遍历:从根集中的每个对象开始,通过对象之间的引用关系,递归地遍历对象图。遍历过程中,将访问到的对象标记为"可达"

  • 标记阶段:标记阶段是遍历过程中的核心步骤,通过对每个对象进行标记,将其标记为可达或不可达。已经标记为可达的对象说明它们仍然被根集或其他可达对象引用,而未标记的对象则被判定为垃圾对象

  • 清除阶段:在标记阶段完成后,垃圾回收器会遍历整个堆内存,将未标记的对象进行清除,释放其占用的内存空间。清除后的内存空间可以被重新利用

优点:

  • 解决循环引用:通过从根集出发,仅标记可达的对象,不可达的对象将被判断为垃圾,即使存在循环引用也能正确回收
  • 高效性:可达性分析算法的效率较高,它只对可达对象进行标记,不需要扫描整个堆内存

垃圾对象回收算法

标记清除算法

基本步骤:

  • 标记阶段:通过可达性分析算法,将可达的对象进行标记,未标记的对象则被标记为垃圾
  • 清除阶段:垃圾回收器遍历整整个堆内存,将未标记的对象进行清除,清除后的内存空间可以被重新利用

缺点:

  • 内存碎片化:标记清除算法会在清除阶段产生内存碎片,即被标记未垃圾袋对象所占用的内存空间,从而导致被释放的空闲空间是零散的不是连续的,可能会导致申请大一点连续内存空间的时候申请失败!
  • 垃圾回收的停顿时间:在标记和清除过程中,垃圾回收器需要暂停应用程序的执行。这种停顿时间可能导致应用程序的响应性能下降,特别是当堆内存较大且垃圾对象较多时


复制算法

  • 针对内存碎片问题,引入的算法

基本步骤:

  • 标记阶段:通过可达性分析算法,将所有可达对象进行标记
  • 复制阶段:在复制阶段,垃圾回收器将标记对象从 From区 复制到 To区 复制过程中,对象的存储地址发送变化,即对象被移动到 To 区
  • 更新引用阶段:完成复制阶段后,需要更新所有指向被复制对象的引用,使其指向对象在 To区的新地址
  • 交换空间:完成引用更新后,From区 和 To区 的角色互换,这样下一次的垃圾回收操作将在新的 To区 进行

缺点:

  • 内存开销:复制算法需要将存活对象复制到 To区,因此需要额外的内存空间来存放复制的对象,从而会增加内存的开销,尤其当存活对象较多时
  • 复制操作的时间开销:复制算法需要将存活对象复制到 To区,这涉及对象的拷贝操作,可能会增加垃圾回收的时间开销。

标记整理算法

  • 针对复制算法内存开销大,引入的算法

基本步骤:

  • 标记阶段:通过可达性分析算法,将所有可达对象进行标记

  • 整理拷贝阶段:垃圾回收器从堆的起始位置开始,依次复制所有活动的对象到堆的另一端,并按顺序排列。拷贝过程中,对象的存储地址发生变化

  • 整理更新引用关系阶段:在拷贝阶段中,垃圾回收器会更新所有指向被复制对象的引用,使其指向对象在新位置的地址。​​​​​

  • 更新根集:在整理阶段完成后,垃圾回收器需要更新根集中的引用,使其指向对象在新位置的地址

  • 空间回收:整理阶段完成后,垃圾回收器可以释放整理前的内存空间,从而减少内存碎片

缺点:

  • 整理过程的时间开销:标记整理算法需要将存活对象整理并移动,这可能涉及对象的拷贝和引用更新操作,增加了垃圾回收的时间开销

  • 停顿时间:在整理阶段,垃圾回收器需要暂停应用程序的执行。这种停顿时间可能影响应用程序的响应性能,特别是当堆内存较大且存活对象较多时


分代算法

  • 总和上述三种算法,通过区域划分,实现不同区域使用不同的垃圾回收算法,从而提高垃圾回收的总体效率

经验规律:

  • 大部分对象在其生命周期中熬不过一轮 GC,即很快成为垃圾,而被回收
  • 一个对象能经过多轮 GC 而不被回收,说明该对象大概率还会长时间的继续存在下去

算法解释: 

新生代:

新生代用于存放新创建的对象。通常采用 复制算法 作为垃圾回收策略。新生代被划分为两个区域:伊甸区和两个生存区。新创建的对象首先分配在伊甸区,当伊甸区满时,仍然存活的对象将被复制到一个生存区,然后在两个生存区之间进行复制和清理。经过多次复制后仍然存活的对象会被晋升到老年代

老年代:

老年代用于存放存活时间较长的对象。由于老年代的对象存活时间更长,GC 的频率相对较低,因此采用 标记整理算法。老年代的垃圾回收相对较少频繁,因为大多数对象在新生代就被回收了

优点:

  • 针对对象生命周期的优化:分代算法通过针对不同代的不同垃圾回收策略,针对对象的生命周期进行优化。新生代采用复制算法,可以迅速回收大部分短命对象,而老年代采用更成熟的垃圾回收算法,适应长寿命对象的特点。

  • 减少垃圾回收的范围:由于大部分对象很快就变得不可达,将堆内存划分为代可以将垃圾回收的范围缩小到新生代,从而减少了垃圾回收的开销。

  • 提高垃圾回收的效率:通过根据对象生命周期的特点采用不同的垃圾回收策略,分代算法可以提高垃圾回收的效率。新生代采用复制算法,具有高效的回收速度,而老年代采用更成熟的算法,可以更好地处理长寿命对象。

注意:若新创建的对象非常大,则直接进入老年代,因为一个大对象进行复制算法,其开销比较大,而且因为它是一个大对象,费很大的开销所创建出来的,很大可能是不会立即销毁的

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

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

相关文章

每日一题(链表中倒数第k个节点)

每日一题(链表中倒数第k个节点) 链表中倒数第k个结点_牛客网 (nowcoder.com) 思路: 如下图所示:此题仍然定义两个指针,fast指针和slow指针,假设链表的长度是5,k是3,那么倒数第3个节点就是值为…

【Jenkins打包服务,Dockerfile报错:manifest for java : 8 not fourd】

1、问题描述 Jenkins打包服务运行dockerfile里的FROM java:8报错manifest for java : 8 not fourd Caused by: com.spotify. docker.client.exceptions.DockerException: manifest for java:8 not found2、解决方法 在网上查找许多方法后得出这是由于Docker官方已经弃用java…

Java自定义异常

Java标准库定义的常用异常包括&#xff1a; 当我们在代码中需要抛出异常时&#xff0c;尽量使用JDK已定义的异常类型。例如&#xff0c;参数检查不合法&#xff0c;应该抛出IllegalArgumentException&#xff1a; static void process1(int age) {if (age < 0) {throw new…

7.2 项目2 学生通讯录管理:文本文件增删改查(C 版本)(自顶向下设计+断点调试) (A)

C自学精简教程 目录(必读) 该作业是 作业 学生通讯录管理&#xff1a;文本文件增删改查&#xff08;C版本&#xff09; 的C 语言版本。 具体的作业题目描述&#xff0c;要求&#xff0c;可以参考 学生通讯录管理&#xff1a;文本文件增删改查&#xff08;C版本&#xff09;。…

CentOS配置Java环境报错-bash: /usr/local/jdk1.8.0_381/bin/java: 无法执行二进制文件

CentOS配置Java环境后执行java -version时报错&#xff1a; -bash: /usr/local/jdk1.8.0_381/bin/java: 无法执行二进制文件原因是所使用的jdk的版本和Linux内核架构匹配不上 使用以下命令查看Linux架构&#xff1a; [rootlocalhost ~]# cat /proc/version Linux version 3.1…

当众讲话紧张不敢说话怎么办?

当在公众场合讲话时&#xff0c;紧张和不敢说话是很常见的问题。这种情况下&#xff0c;以下是一些帮助你克服紧张并提高自信的技巧和建议&#xff1a; 1. 准备充分&#xff1a;充分的准备是克服紧张的关键。在讲话前&#xff0c;确保你对主题有足够的了解&#xff0c;并进行适…

stable diffusion实践操作-webUI教程

系列文章目录 stable diffusion实践操作 提示&#xff1a;写完文章后&#xff0c;目录可以自动生成&#xff0c;如何生成可参考右边的帮助文档 文章目录 系列文章目录前言一、SD webUI是什么&#xff1f;二、详细教程1. 插件安装1.1. 提示词插件安装和使用 2. xyz 图表使用2.1…

基于单片机的点阵电子显示屏上下左右移加减速系统

一、系统方案 本设计的任务就是完成一个1616的点阵设计&#xff0c;并能滚动显示“********************”内容。 主要内容是&#xff0c;能同时流动显示汉字&#xff1b;能实现显示汉字无闪烁&#xff1b;能实屏幕亮度较高。本LED显示屏能够以动态扫描的方式显示一个1616点阵汉…

Spring Boot日志基础使用 设置日志级别

然后 我们来说日志 日志在实际开发中还是非常重要的 即可记录项目状态和一些特殊情况发生 因为 我们这里不是将项目 所以 讲的也不会特别深 基本还是将Spring Boot的日志设置或控制这一类的东西 相对业务的领域我们就不涉及了 日志 log 初期最明显的作用在于 开发中 你可以用…

stable diffusion实践操作-embedding(TEXTUAL INVERSION)

系列文章目录 本文专门开一节写图生图相关的内容&#xff0c;在看之前&#xff0c;可以同步关注&#xff1a; stable diffusion实践操作 文章目录 系列文章目录前言1、embeddding的功能2、如何去下载(https://civitai.com/models)2.1 筛选 TEXTUAL INVERSION2.2 筛选出来2.3 下…

构建现代应用:Java中的热门架构概览

文章目录 1. 三层架构2. Spring框架3. 微服务架构4. Java EE&#xff08;Enterprise Edition&#xff09;5. 响应式架构6. 大数据架构7. 领域驱动设计&#xff08;Domain-Driven Design&#xff0c;DDD&#xff09;8. 安卓开发架构结论 &#x1f389;欢迎来到Java学习路线专栏~…

RNN 单元:分析 GRU 方程与 LSTM,以及何时选择 RNN 而不是变压器

一、说明 深度学习往往感觉像是在雪山上找到自己的道路。拥有坚实的原则会让你对做出决定更有信心。我们都去过那里 在上一篇文章中&#xff0c;我们彻底介绍并检查了 LSTM 单元的各个方面。有人可能会争辩说&#xff0c;RNN方法已经过时了&#xff0c;研究它们是没有意义的。的…

真机安装Linux Centos7

准备工具&#xff1a; 8G左右U盘最新版UltraISOCentOS7光盘镜像 操作步骤 下载镜像 地址&#xff1a;http://isoredirect.centos.org/centos/7/isos/x86_64/ 安装刻录工具UltraISO&#xff0c;刻录镜像到U盘 ① 选择ISO镜像文件 ② 写入磁盘镜像&#xff0c;在这里选择你的U盘…

【云原生】Ansible自动化批量操作工具playbook剧本

目录 1.playbook相关知识 1.1 playbook 的简介 1.2 playbook的 各部分组成 2. 基础的playbook剧本编写实例 2.1 playbook编写Apache安装剧本&#xff08;yum方式安装&#xff09; 报错集&#xff1a; 实例2&#xff1a;playbook编写nginx 的yum安装并且能修改其监听端口的…

北京APP外包开发团队人员构成

下面是一个标准的APP开发团队构成&#xff0c;但具体的人员规模和角色可能会根据项目的规模和需求进行调整。例如&#xff0c;一些小型项目或初创公司可能将一些角色合并&#xff0c;或者聘请外包团队来完成部分工作。北京木奇移动技术有限公司&#xff0c;专业的软件外包开发公…

PYTHON知识点学习-函数(下)

&#x1f308;write in front&#x1f308; &#x1f9f8;大家好&#xff0c;我是Aileen&#x1f9f8;.希望你看完之后&#xff0c;能对你有所帮助&#xff0c;不足请指正&#xff01;共同学习交流. &#x1f194;本文由 Aileen_0v0&#x1f9f8; 原创 CSDN首发&#x1f412; 如…

Matlab图像处理-幂次变换

幂次变换 如下图所示的幂次变换函数曲线图&#xff1a; 当γ <1时&#xff0c;效果和对数变换相似&#xff0c;放大暗处细节&#xff0c;压缩亮处细节&#xff0c;随着数值减少&#xff0c;效果越强。 当γ >1时&#xff0c;放大亮处细节&#xff0c;压缩暗处细节&…

大语言模型之七- Llama-2单GPU微调SFT

&#xff08;T4 16G&#xff09;模型预训练colab脚本在github主页面。详见Finetuning_LLama_2_0_on_Colab_with_1_GPU.ipynb 在上一篇博客提到两种改进预训练模型性能的方法Retrieval-Augmented Generation (RAG) 或者 finetuning。本篇博客过一下模型微调。 微调&#xff1a…

YOLOV8模型使用-检测-物体追踪

这个最新的物体检测模型&#xff0c;很厉害的样子&#xff0c;还有物体追踪的功能。 有官方的Python代码&#xff0c;直接上手试试就好&#xff0c;至于理论&#xff0c;有想研究在看论文了╮(╯_╰)╭ 简单介绍 YOLOv8 中可用的模型 YOLOv8 模型的每个类别中有五个模型用于检…

Linux常用命令——cupsenable命令

在线Linux命令查询工具 cupsenable 启动指定的打印机 补充说明 cupsenable命令用于启动指定的打印机。 语法 cupsenable(选项)(参数)选项 -E&#xff1a;当连接到服务器时强制使用加密&#xff1b; -U&#xff1a;指定连接服务器时使用的用户名&#xff1b; -u&#xff…