当前位置: 首页 > news >正文

JVM之【GC-可达性分析算法】

在Java虚拟机(JVM)中,可达性分析算法(Reachability Analysis)用于垃圾收集,以确定哪些对象是“可达”的,即哪些对象仍然有用,哪些对象可以被回收。下面是对可达性分析算法及其底层实现的详细描述。

可达性分析算法概述

可达性分析算法通过从一组称为"根对象"(GC Roots)的对象开始,遍历对象引用图,确定哪些对象是可达的。那些无法从根对象访问到的对象被视为不可达的,可以被垃圾收集器回收。

根对象(GC Roots)

在JVM中,根对象包括以下几类:

  1. 虚拟机栈中的引用:包括各个线程的栈帧中的本地变量表中引用的对象。
  2. 方法区中的类静态属性引用的对象:即静态字段引用的对象。
  3. 方法区中的常量引用的对象:如字符串常量池中的引用。
  4. 本地方法栈中的引用:即JNI(Java Native Interface)引用的对象。
  5. 所有被同步锁synchronized持有的对象

所以!GC Roots是很多很多个的,而不要看到Roots就认为只有一个

可达性分析过程

可达性分析的过程可以概括为以下几个步骤:

  1. 标记阶段
    • 从GC Roots开始,将所有可达对象标记为活跃。
    • 使用一种图遍历算法(如深度优先搜索DFS或广度优先搜索BFS)遍历对象引用图,找到所有可达对象。
  2. 清除阶段
    • 在标记阶段之后,所有未被标记的对象被视为不可达,可以被垃圾收集器回收。
  • 如果要使用可达性分析算法来判断内存是否可回收,那么分析工作必须在一个能保障一致性的快照中进行。否则分析结果的准确性就无法保证
  • 这也是导致GC时必须“Stop the World” 的一个重要原因!!

底层实现

  1. 对象引用图

    • JVM内部使用一种称为“对象图”的数据结构来表示对象及其相互引用关系。对象图中的每个节点表示一个对象,每条边表示一个对象对另一个对象的引用。
  2. 标记-清除算法(Mark-Sweep Algorithm)

    • 标记阶段:Collector从GC Roots开始,遍历对象图,对所有访问到的对象进行标记。标记通常通过在对象头部设置标志位来实现。
    • 清除阶段:Collector遍历堆中的所有对象,回收那些未被标记的对象。
    • 缺点
      • 效率不高
      • GC的时候需要stop整个应用程序
      • 清理出来的内存不连续,即不会整合内存,而是复用垃圾对象的内存。会存在大量内存碎片
  3. 并发标记-清除算法

    • 在现代JVM中,为了减少垃圾收集带来的暂停时间(stop-the-world),通常会采用并发标记-清除算法。这些算法允许应用线程和垃圾收集线程同时工作。
    • 三色标记法:是并发标记的一种实现方式,通过将对象标记为白色、灰色和黑色来实现。
      • 白色:尚未访问的对象。
      • 灰色:已访问但未处理完引用的对象。
      • 黑色:已访问且引用已处理完的对象。
    • 并发标记阶段:
      • 初始标记:标记从根对象直接可达的对象,通常会短暂暂停所有应用线程。
      • 并发标记:与应用线程并发运行,标记所有可达对象。
      • 最终标记:处理并发标记期间产生的引用变化,通常会有短暂停顿。
    • 清除阶段:回收未被标记的对象。
  4. 分代垃圾回收

    • JVM通常采用分代垃圾回收策略,将堆分为年轻代和老年代。不同代使用不同的回收算法以优化性能。
    • 年轻代使用复制算法(复制存活对象到新的区域,回收旧区域的所有对象)。
    • 老年代使用标记-清除或标记-整理算法(将存活对象压缩到一侧,回收剩余空间)。

根对象和其他对象的连接

  1. 引用链

    • 根对象通过引用链(Reference Chain)连接到其他对象。每个对象都有字段指向其他对象,这些字段形成了对象图中的边。
    • 在标记阶段,算法通过引用链从根对象递归或迭代地访问其他对象。
  2. 栈和静态变量的引用

    • 虚拟机栈中的本地变量表和方法区中的静态变量表保存着对对象的直接引用。这些引用成为可达性分析的起点。

通过以上步骤和机制,JVM能够有效地识别和回收不可达的对象,从而管理堆内存并保证应用程序的正常运行和性能。

相关文章:

  • redis面试知识点
  • oracle 还原被覆盖的视图
  • 算法每日一题(python,2024.05.29) day.11
  • 【Java基础-注解】Java中注解的分类有哪些,如何自定义一个注解,并使用举例
  • String常用操作
  • HashMap与Hashtable的异同
  • C语言:学生成绩管理系统(含源代码)
  • 【机器学习】机器学习与AI大数据的融合:开启智能新时代
  • Redis教程(十九):Redis的Redisson布隆过滤器
  • 定义类并创建类的实例
  • 【EFK日志系统】在kibana操作索引模板、生命周期、管道等
  • 通过提示工程将化学知识整合到大型语言模型中
  • Java实现对PDF、纵向、横向页面添加自定义水印功能
  • 堡垒机,日志审计系统,行为管理,漏洞扫描的作用
  • 【熊熊双语绘本】3、飞向星空的小火箭
  • [原]深入对比数据科学工具箱:Python和R 非结构化数据的结构化
  • 《网管员必读——网络组建》(第2版)电子课件下载
  • 【407天】跃迁之路——程序员高效学习方法论探索系列(实验阶段164-2018.03.19)...
  • 【vuex入门系列02】mutation接收单个参数和多个参数
  • Android 控件背景颜色处理
  • C++类中的特殊成员函数
  • C语言笔记(第一章:C语言编程)
  • JS笔记四:作用域、变量(函数)提升
  • Linux快速配置 VIM 实现语法高亮 补全 缩进等功能
  • Material Design
  • Swift 中的尾递归和蹦床
  • windows下mongoDB的环境配置
  • 后端_MYSQL
  • 阿里云ACE认证学习知识点梳理
  • 支付宝花15年解决的这个问题,顶得上做出十个支付宝 ...
  • (11)MATLAB PCA+SVM 人脸识别
  • (11)工业界推荐系统-小红书推荐场景及内部实践【粗排三塔模型】
  • (cljs/run-at (JSVM. :browser) 搭建刚好可用的开发环境!)
  • (iPhone/iPad开发)在UIWebView中自定义菜单栏
  • (搬运以学习)flask 上下文的实现
  • (二)c52学习之旅-简单了解单片机
  • (附源码)ssm基于微信小程序的疫苗管理系统 毕业设计 092354
  • (三)Kafka 监控之 Streams 监控(Streams Monitoring)和其他
  • (转)Linux下编译安装log4cxx
  • (转)memcache、redis缓存
  • .aanva
  • .NET 回调、接口回调、 委托
  • .net 简单实现MD5
  • .NET性能优化(文摘)
  • .NET中的Exception处理(C#)
  • /proc/stat文件详解(翻译)
  • @Bean有哪些属性
  • [ 云计算 | AWS ] 对比分析:Amazon SNS 与 SQS 消息服务的异同与选择
  • []sim300 GPRS数据收发程序
  • [Algorithm][动态规划][简单多状态DP问题][按摩师][打家劫舍Ⅱ][删除并获得点数][粉刷房子]详细讲解
  • [AutoSar]BSW_Com02 PDU详解
  • [codeforces]Levko and Permutation
  • [EFI]Atermiter X99 Turbo D4 E5-2630v3电脑 Hackintosh 黑苹果efi引导文件
  • [HTML API]HTMLCollection
  • [html] 动态炫彩渐变背景