【Java】刚刚!突然!紧急通知!垃圾回收!

【Java】刚刚!突然!紧急通知!垃圾回收!

文章目录

  • 【Java】刚刚!突然!紧急通知!垃圾回收!
    • 从C语言的内存管理引入:手动回收
    • Java的垃圾回收机制
      • 引用计数器
        • 循环引用问题
      • 可达性分析法与GC Root
        • GC Root的典型例子
      • 标记-清除算法
        • 优点
        • 缺点
      • 复制算法
        • 工作原理
        • 优点
        • 缺点
      • 标记-整理算法
        • 工作原理
        • 优点
        • 缺点
      • 应用场景
      • 分代回收机制
        • 堆内存的分代
        • 各代的垃圾回收策略
          • 新生代垃圾回收(Minor GC)
          • 老年代垃圾回收(Major GC 或 Full GC)
      • 结语

本文将先简要介绍C语言的手动内存回收机制,然后深入探讨Java的垃圾回收(GC)机制,包括引用计数器、可达性分析法、GC root、标记-清除算法、复制算法、标记-整理算法以及分代回收机制。

从C语言的内存管理引入:手动回收

在C语言中,程序员需要手动管理内存的分配和释放。这主要通过malloccallocreallocfree函数来实现:

  • malloc:用于动态分配内存。
  • calloc:类似于malloc,但它会初始化分配的内存块为零。
  • realloc:用于调整先前分配的内存块的大小。
  • free:用于释放动态分配的内存。

虽然这种手动管理提供了很大的灵活性,但也容易导致内存泄漏(未释放不再使用的内存)和悬挂指针(指向已释放内存的指针)。这就需要程序员特别小心,确保每一块动态分配的内存都能被适时释放。

例如:

img

我们使用malloc,为结点结构体的指针分配内存。

而在删除节点时,我们采用free函数来进行内存的释放。

image-20240530215713904

Java的垃圾回收机制

与C语言不同,Java提供了自动内存管理功能。Java的垃圾回收机制旨在自动回收不再使用的对象所占用的内存,从而减轻程序员的负担并提高内存管理的安全性。

引用计数器

最简单的垃圾回收机制之一是引用计数器。它通过维护每个对象的引用计数来跟踪对象是否可以被回收:

  • 引用计数增加:每当一个新的引用指向对象时,引用计数加1。
  • 引用计数减少:每当一个引用被销毁或被设置为指向另一个对象时,引用计数减1。
  • 回收对象:当对象的引用计数变为0时,说明该对象不再被使用,可以被回收。

然而,引用计数器存在一个明显的缺点,即无法处理循环引用(两个对象相互引用)。

循环引用问题

引用计数器的一大缺点是无法处理循环引用。如下示例:

class Node {Node next;
}Node a = new Node();
Node b = new Node();
a.next = b;
b.next = a;

在这个例子中,即使ab对象的引用离开了作用域,它们的引用计数器仍然不为0(因为它们互相引用),导致内存泄漏。

因此,Java并不使用这种方法作为其主要的垃圾回收策略。

可达性分析法与GC Root

Java采用的是更为先进的可达性分析法。它通过一组被称为GC Root的根对象作为起点,沿着这些根对象的引用链进行搜索。如果一个对象能从GC Root到达,那么它就是可达的(alive),否则就是不可达的,可以被回收。

  • GC Root:通常包括当前在栈中引用的对象、静态变量引用的对象以及JNI(Java Native Interface)引用的对象等。
  • 可达对象:从GC Root开始,所有可以通过引用链访问到的对象都是可达的。
  • 不可达对象:如果一个对象没有从GC Root出发的任何引用链到达,则认为该对象是不可达的,可以被回收。

image-20240531191720169

GC Root的典型例子
  • 虚拟机栈中的引用对象:如栈帧中的局部变量和输入参数。
  • 方法区中的静态引用:如类的静态属性。
  • 方法区中的常量引用:如常量池中的引用。

标记-清除算法

image-20240531191636409

标记-清除算法是最早且最基本的垃圾回收算法之一。标记-清除算法分为两个阶段:标记阶段和清除阶段。

  1. 标记阶段
    • 从GC Root集合开始,遍历对象引用图,标记所有可达的对象。
    • 标记过程通常是递归的,沿着对象引用链进行,直到所有可达的对象都被标记。
  2. 清除阶段
    • 遍历堆中的所有对象,回收未被标记的对象。
    • 未标记的对象被认为是不可达的,可以被垃圾回收器回收。

image-20240531191652410

优点
  • 简单直接:算法简单,易于实现。
  • 无需移动对象:对象在内存中的位置不会改变,减少了对象移动的开销。
缺点
  • 内存碎片:清除阶段后,未被回收的对象会在堆中留下许多空闲区域,导致内存碎片。频繁的内存碎片会降低内存分配效率。
  • 标记和清除过程需要遍历所有对象:在大堆内存中,遍历所有对象可能导致较长的暂停时间。

复制算法

工作原理

复制算法将堆内存分为两部分,通常是等大小的两个半区:From空间和To空间。垃圾回收时,仅使用其中一个半区,另一个半区作为备用空间。

  1. 分配阶段

    • 对象只在From空间中分配内存。
    • To空间为空闲的,等待垃圾回收。
  2. 复制和清理阶段

    • 从GC Root开始,遍历所有可达的对象,并将它们复制到To空间。
    • 复制过程中,保持对象的引用关系。
    • 完成复制后,From空间中的所有对象被认为是不可达的,可以被回收。
    • 交换From和To空间的角色,下一次分配和垃圾回收使用新的From空间。
  3. 示例

    假设有A块等待垃圾回收:

    image-20240531191812980

    回收之后会变成~:

    image-20240531191937607

优点
  • 无内存碎片:对象被紧凑地复制到新的空间,不会留下内存碎片。
  • 分配速度快:由于始终从一个连续的空闲区域分配内存,分配速度很快。
缺点
  • 内存利用率低:由于堆内存被划分为两个半区,同时只使用一半内存,导致内存利用率低。
  • 对象复制开销:复制对象到新的空间需要额外的开销,特别是当对象较多时。

标记-整理算法

标记-整理算法(Mark-Compact Algorithm)是一种改进的垃圾回收算法,用于解决标记-清除算法产生的内存碎片问题。它结合了标记-清除和复制算法的优点,通过整理内存来提高内存分配效率。下面将详细分析标记-整理算法的工作原理、优缺点及其适用场景。

工作原理

标记-整理算法也分为两个主要阶段:标记阶段和整理阶段。

  1. 标记阶段

    • 从GC Root集合开始,遍历对象引用图,标记所有可达的对象。
    • 这一步与标记-清除算法中的标记阶段相同,标记过程是递归的,沿着对象引用链进行,直到所有可达的对象都被标记。

    image-20240531192004795

  2. 整理阶段

    • 遍历整个堆,将所有存活的对象向一端移动(通常是堆的起始位置),保持对象之间的紧密排列。
    • 更新所有对象的引用,以反映它们的新位置。
    • 移动完成后,释放未被标记对象的内存,未被标记的对象被回收,形成一块连续的空闲区域。

    image-20240531192017499

优点
  • 无内存碎片:对象被紧密排列在一起,没有内存碎片,提高了内存利用率。
  • 高效的内存分配:由于所有存活对象被移动到堆的一端,剩下的内存是连续的,内存分配速度更快。
  • 适用于长生命周期对象:尤其适合老年代(Old Generation)的垃圾回收,因为老年代对象生命周期较长,不需要频繁移动。
缺点
  • 对象移动开销:整理阶段需要移动对象,并更新引用,增加了额外的开销,尤其是在老年代中存活对象较多时。
  • 暂停时间长:标记和整理过程会导致应用暂停,可能影响实时性要求较高的应用。

标记-整理算法减少了内存碎片化,同时避免了复制算法中需要双倍内存的缺点。

应用场景

  • 标记-清除算法:适用于内存紧张、不希望频繁移动对象的场景,如老年代(Old Generation)的垃圾回收。
  • 复制算法:适用于对象生命周期短、需要快速回收的场景,如新生代(Young Generation)的垃圾回收。JVM中的新生代垃圾回收器通常使用复制算法。
  • 标记-整理算法:对象较大且数量较多的场景,当对象较大且数量较多时,标记-整理算法可以通过紧凑排列对象,减少内存浪费,提高内存利用率。

分代回收机制

分代回收机制的核心思想是将堆内存划分为几个代,根据对象的生命周期长短来进行不同的管理和回收。大多数对象的生命周期很短,少数对象存活时间较长。通过这种划分,可以有针对性地采用不同的垃圾回收算法,提高回收效率和性能。

堆内存的分代

JVM中的堆内存通常划分为以下几代:

新生代(Young Generation)

  • Eden区:所有新创建的对象首先分配在Eden区。
  • 两个Survivor区(S0和S1):用于在新生代中进行对象复制和存活对象的管理。每次垃圾回收时,存活的对象从Eden区和一个Survivor区复制到另一个Survivor区。

老年代(Old Generation):存活时间较长、从新生代晋升的对象存放在老年代。

永久代(PermGen)或元空间(Metaspace):存储类的元数据(方法、类结构等)。在Java 8之前为永久代(PermGen),Java 8及之后为元空间(Metaspace)。

各代的垃圾回收策略
新生代垃圾回收(Minor GC)

新生代的垃圾回收频繁,通常采用复制算法(Copying Algorithm)。当Eden区填满时,触发Minor GC:

  1. 存活对象复制:存活的对象从Eden区和一个Survivor区复制到另一个Survivor区。
  2. 对象晋升:当对象经过多次Minor GC后依然存活(达到一定年龄),或Survivor区空间不足时,存活对象晋升到老年代。
  3. Eden区清空:所有存活对象复制后,Eden区和一个Survivor区被清空,另一个Survivor区保留存活对象。

Minor GC的频率较高,但由于新生代对象生命周期短,存活对象少,因此回收速度较快。

老年代垃圾回收(Major GC 或 Full GC)

老年代的垃圾回收通常采用标记-整理算法(Mark-Compact Algorithm) 或 标记-清除算法(Mark-Sweep Algorithm)

  1. 标记阶段:从GC Root开始,标记所有可达的对象。
  2. 整理阶段(标记-整理算法):将所有存活对象向一端移动,保持对象之间的紧密排列,释放未标记对象的内存。
  3. 清除阶段(标记-清除算法):回收未标记对象的内存,但可能产生内存碎片。

Major GC或Full GC的频率较低,但由于老年代对象较多且存活时间长,回收过程较慢,可能导致较长的暂停时间。

结语

Java的垃圾回收机制通过自动化内存管理,极大地减轻了开发者的负担,同时提升了程序的安全性和稳定性。尽管Java的GC机制复杂多样,但其核心思想都是为了更高效地管理内存,避免内存泄漏和碎片化。

许多现代编程语言,如Java、C#、Python等,都内置了垃圾回收机制。通过学习垃圾回收,可以更深入地理解这些语言的设计思想和实现细节。不同语言的垃圾回收机制有所不同,了解这些差异可以帮助我们在具体语言中应用最佳实践,编写高效的代码。

此后,笔者还会介绍Java中的垃圾回收器相关知识,以及有可能的JVM调优。

参考资料与文献:

20、垃圾回收算法之可达性分析法和GC Roots是什么?_哔哩哔哩_bilibili

【JVM】万字长文!深入详解Java垃圾回收(GC)机制_java gc-CSDN博客

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

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

相关文章

SpringBoot六种API请求参数读取方式

SpringBoot六种API请求参数读取方式 同步请求和异步请求 同步: 指单线程依次做几件事异步: 指多线程同时做几件事 同步请求: 指客户端浏览器只有一个主线程, 此线程负责页面的渲染和发出请求等操作, 如果此主线程发出请求的话则停止渲染而且会清空页面显示的内容 直到服务器响…

优化基础(二):线性组合、仿射组合、锥组合、凸组合、线性集合、仿射集合、锥集合、凸集合的理解

文章目录 前言组合线性组合 (linear combination)仿射组合 (affine combination)锥组合 (conic combination)凸组合 (convex combination) 集合仿射集合凸集合 练习:哪个图形是凸的,哪个是仿射的?参考资料 前言 组合侧重于描述由一些基点生成…

越洗越黑”的Pandas数据清洗

引言 先来一个脑筋急转弯活跃一下枯燥工作日常,问:“什么东西越洗越黑?” 有没有猜到的?猜不到我告诉你吧! 答案是“煤球”。那么这个脑机急转弯跟我们要讨论的话题有没有关系呢? 嗯是的,还是沾…

三相智能电表通过Modbus转Profinet网关与PLC通讯案例

Modbus转Profinet网关(XD-MDPN100/300)的主要功能是实现Modbus协议和Profinet协议之间的转换和通信。Modbus转Profinet网关集成了Modbus和Profinet两种协议,支持Modbus RTU主站/从站,并可以与RS485接口的设备,它自带网…

接口请求参数为文件时如何测试

方法 工具:Postman 步骤:①点击body②点击form-data③选择key类型为fie ④输入参数名⑤选择参数上传⑥发送请求

对称二叉树(oj题)

一、题目链接https://leetcode-cn.com/problems/symmetric-tree/ 二、题目思路 给你一个二叉树的根节点 root , 检查它是否轴对称的思路: 1.将该树的左子树和右子树,当做两棵树,调用 判断两棵树是否对称相等的函数 2.判断两颗树是否对称相…

告别低效提问:掌握BARD技巧,让AI成为你的智能助手!

今天只聊一个主题:提示词 Prompt。 说到提示词,大家可能都看过GPT的高级示例,那些几百字的提示词,写起来确实不容易。 那么,如何写出同样效果的提示词呢? 有没有什么公式或者系统学习的方法?…

木叶飞舞之【机器人ROS2】篇章_第三节、给turtlebot3安装realsense深度相机

我们做视觉slam时会用到深度相机,但是gazebo的turtlebot3中只有rgb相机,没有深度,因此本节会修改代码,来给我们的小乌龟增加一个rgbd相机。 效果展示 发布topic如下图 图片大小都是640*480 1. 修改model.sdf文件 1.1 路径位置…

启智CV机器人,ROS, ubuntu 18.04

资料: https://wiki.ros.org/kinetic/Installation/Ubuntu https://blog.csdn.net/qq_44339029/article/details/120579608 http://wiki.ros.org/melodic/Installation/Ubuntu https://github.com/6-robot/wpb_cv 一、安装ros环境 装VM。 装ubuntu18.04 desktop.…

100道面试必会算法-27-美团2024面试第一题-前缀和矩阵

100道面试必会算法-27-美团2024面试第一题-前缀和矩阵 问题解读 给定一个 n x n 的二进制矩阵,每个元素是 0 或 1。我们的任务是计算矩阵中所有边长为 k 的子矩阵中,包含特定数量 1 的情况。例如,我们希望找到所有边长为 k 的子矩阵中包含 k…

【学习Day3】计算机基础

✍🏻记录学习过程中的输出,坚持每天学习一点点~ ❤️希望能给大家提供帮助~欢迎点赞👍🏻收藏⭐评论✍🏻指点🙏 1.5.4 Cache替换算法 Cache的页面淘汰算法 常用替换算法有: • 随机替换算法RA…

vue3 setup 使用 beforeRouteEnter 组件内路由守卫

vue3 setup 使用 beforeRouteEnter 组件内路由守卫 setup 中只有onBeforeRouteLeave、onBeforeRouteUpdate两个钩子函数&#xff0c; 没有beforeRouteEnter对应的钩子函数&#xff0c;所以无法在setup中直接使用 <script setup> onBeforeRouteLeave((to, from) > {// …

3D软件开发的相关技术

3D开发涉及到广泛的技术和工具&#xff0c;涵盖了多个领域&#xff0c;包括计算机图形学、编程、设计、物理模拟等。以下是3D开发中常用的技术和工具&#xff0c;掌握这些技术需要广泛的知识和实践&#xff0c;项目的成功依赖于对这些技术的有效整合和应用。北京木奇移动技术有…

音视频开发14 FFmpeg 视频 相关格式分析 -- H264 NALU格式分析

H264简介-也叫做 AVC H.264&#xff0c;在MPEG的标准⾥是MPEG-4的⼀个组成部分–MPEG-4 Part 10&#xff0c;⼜叫Advanced Video Codec&#xff0c;因此常常称为MPEG-4 AVC或直接叫AVC。 原始数据YUV,RGB为什么要压缩-知道就行 在⾳视频传输过程中&#xff0c;视频⽂件的传输…

热敏电阻的设计

热敏电阻(NTC)的作用&#xff1a;抑制开机时的浪涌电流。防止开机瞬间产生的浪涌电流损坏后面的元件。 取值依据:根据对开机的脉冲电流&#xff08;浪涌电流&#xff09;小于多少A&#xff1f; 由,这个U是指最大输入电压&#xff0c;I为要求的浪涌电流。 NTC是负温度系数的热…

收银系统源码--商超水果生鲜店收银硬件要怎么选择?

新零售时代&#xff0c;越来越多的商家开始明白&#xff0c;除了要做好店铺定位、店面装潢和商品的设定&#xff0c;还要选购最适合店铺运营需求的收银机和硬件&#xff0c;好的收银机和收银系统可以帮助商家做好收支统计、库存管理、人员配置。客户服务等工作。现在的智能收银…

MySQL 索引使用(二)

本篇继续介绍有关索引的使用。 目录 一、SQL提示 二、单列索引和联合索引 三、覆盖索引 四、前缀索引 五、索引的使用原则 一、SQL提示 我们在使用索引来进行查询时&#xff0c;很有可能会出现一个字段中包含多个索引的情况&#xff0c;例如这里有一个name字段&#xff0c…

从零开始学习Slam-旋转矩阵旋转向量四元组(二)

本文参考&#xff1a;计算机视觉life 仅作笔记用 书接上回&#xff0c;上回不清不楚的介绍了旋转矩阵&旋转向量和四元组 现在回顾一下重点&#xff1a; 本着绕谁谁不变的变则 假设绕z轴旋转θ&#xff0c;旋转矩阵为&#xff1a; 再回顾一下旋转向量的表示以及这个基本记不…

SpringCloud如何实现SSO单点登录?

目录 一、SpringCloud框架介绍 二、什么是SSO单点登录 三、单点登录的必要性 四、SpringCloud如何实现SSO单点登录 一、SpringCloud框架介绍 Spring Cloud是一个基于Spring Boot的微服务架构开发工具集&#xff0c;它整合了多种微服务解决方案&#xff0c;如服务发现、配置…

SpringSecurity6从入门到实战之Filter过滤器回顾

SpringSecurity6从入门到实战之Filter过滤器回顾 如果没有SpringSecurity这个框架,我们应该通过什么去实现客户端向服务端发送请求时,先检查用户是否登录,登录了才能访问.否则重定向到登录页面 流程图如下 官方文档&#xff1a;https://docs.spring.io/spring-security/referen…