JVM 根可达算法

news2024/11/16 1:19:19

Java中的垃圾

Java中"垃圾"通常指的是不再被程序使用和引用的对象,具体表现在没有被栈、JNI指针和永久代对象所引用的对象。Java作为一种面向对象的编程语言,它使用自动内存管理机制,其中垃圾收集器负责检测和回收不再被程序引用的对象,以释放它们占用的内存空间。以下是一些导致对象成为垃圾的常见情况:

  1. 无引用对象: 当一个对象没有任何引用指向它时,它就变得不可达,成为垃圾,Java的垃圾收集器会识别这样的对象,并将它们回收。

  2. 引用循环: 如果一组对象彼此引用形成一个循环,而这个循环与程序的其他部分没有引用相连,那么这个循环中的对象就会成为垃圾。Java的垃圾收集器通过识别引用循环并处理它们来防止内存泄漏。

  3. 显式置空引用: 如果程序员显式地将一个引用置空(null),而没有其他引用指向相同的对象,那么该对象就变成了垃圾。

垃圾收集器周期性地运行,并识别和回收这些垃圾对象,释放其内存中对应的区域以确保内存能够得到有效利用,这种自动的内存管理机制就叫做垃圾回收。

如何寻找垃圾?

引用计数(Reference Count)
引用计数算法是一种垃圾标记,其核心思想是通过维护对象的引用计数来判断对象是否可以被回收。每个对象都有一个关联的引用计数,表示当前有多少个指针引用它。当引用计数为零时,意味着没有指针再引用该对象,因此可以安全地回收该对象的内存。

其实引用计数算法的核心思想就是,只要有对象引用我,那么就说明我是有用的,我还不需要被回收,反正,我就是没有用的对象,那么我和我的子对象都应该被回收掉。这里我们说的对象都是堆上的对象,一般是堆上的内存空间需要程序员手动回收,而栈上的内存空间则由操作系统自行回收。由于栈上的对象是操作系统自行管理和回收的,因此栈上的对象以及一些静态对象始终都是出于存活的状态,因此,堆中存活的对象至少会有一个引用(指针)指向它。

但是这样会存在着一个问题,就是对象中的引用关系形成了环状——循环引用,这种情况下环内所有对象的引用都是>1的,这样一来环内的所有都无法被回收从而造成“内存泄漏”。这是引用算法最主要的局限性,也是为什么JVM不采用循环计数的方法来标记垃圾的原因。

根可达算法(Root Search)

由于引用计数算法无法解决“循环引用”的问题,无可避免的会造成内存泄露,因此,Java没有采用引用计数算法来寻找垃圾。而是采用了一种从GC Roots开始搜索存活对象的垃圾标记算法——根可达算法。
在这里插入图片描述

哪些是GC Root?

  1. 线程栈 (Thread Stacks) :活动线程的栈帧中的本地变量引用的对象。每个线程都有一个栈,栈中的引用对象是潜在的存活对象。
  2. 静态变量 (Static Variables) :类的静态成员变量引用的对象。静态变量随着类的加载而初始化,它们的引用可能使对象保持存活。
  3. 常量池 (Constant Pool) :常量池中的引用,包括字符串常量等。这些常量在类加载时被创建,它们的引用也可能使对象保持存活。
  4. JNI 引用 (JNI References) :通过 JNI 在本地代码中创建的对象引用。如果 Java 代码通过 JNI 调用了本地方法,并在本地方法中创建了对象,这些对象的引用也是 GC Roots。
  5. 监控与管理 MBeans (JMX) :活动的监控、管理 MBeans 等通过 JMX 等管理工具注册的对象。这些对象的引用也被视为 GC Roots。

线程栈 (Thread Stacks)
在Java中,当程序运行的时候线程会将一个个方法放到栈上来执行,并且对于方法局部的一些小的对象和变量也会被分配在栈空间上,而栈空间是由操作系统本身来控制什么时候进行释放和分配的。因此,基于这个逻辑我们可以认为对于当前线程来说,存在于栈空间上的变量都是存活的,而且栈空间一般比较小只有几MB的大小,里面存活的变量和对象都是有限的作为GC Roots来说搜索起来也是非常高效的。

静态变量 (Static Variables)
在Java中静态变量一般是随着类加载的时候被创建和初始化的,和Java字节码一样,静态变量也会被加载到元空间(Meta Space,Java 8之前叫做方法区(Method Area)或叫做永久代(Permanent Generation),Java 8之后叫做元空间)。

元空间的对象是不会轻易被释放的,而静态变量会随着整个类被释放的时候才会被释放,因此静态变量可以作为GC Root来寻找垃圾。

常量池 (Constant Pool)
常量池(Constant Pool)是Java中一种存放常量的数据结构,用于存储编译期生成的字面量和符号引用。常量池属于元空间(Meta Space,Java 8之前叫做方法区(Method Area)或叫做永久代(Permanent Generation),Java 8之后叫做元空间),具体说是类加载后存放在元空间的一部分内存。

在Java程序的编译阶段,常量池会保存各种字面量和符号引用,包括字符串、类和接口的全限定名、字段和方法的名称和描述符等,这些信息在编译后会被存放在class文件的常量池中,在运行期间这些常量池依旧会存在并且Java根据常量池来映射参数。

所以,处于常量池中的变量也可以作为GC Roots来寻找垃圾

JNI 引用 (JNI References)
JNI(Java Native Interface)引用是指在Java程序中通过JNI创建的与本地代码(C++代码,调用平台相关函数)相互调用的引用。JNI引用包括本地引用(Local Reference)、全局引用(Global Reference)和弱全局引用(Weak Global Reference)。

本地引用(Local Reference): 本地引用是一种短期的引用,用于限定其生命周期。当Java方法调用本地方法时,本地引用会被创建,但在本地方法返回后,这些引用将被自动释放。本地引用不能作为GC Roots。

全局引用(Global Reference): 全局引用是一种长期有效的引用,可以在整个程序的生命周期内使用。全局引用可以防止被引用对象被垃圾回收,因此它可以作为GC Roots。

弱全局引用(Weak Global Reference): 弱全局引用也是一种全局引用,但它对被引用对象的生命周期没有强制影响。如果一个对象只被弱全局引用引用,那么它在垃圾回收时可能被回收。弱全局引用不能作为GC Roots。

JNI引用之所以能作为GC Roots,是因为它们可以在本地方法(C++方法,调用平台相关函数)中持有Java对象的引用,防止这些对象在本地方法执行期间被垃圾回收。全局引用在整个程序的生命周期内有效,因此它们有可能成为根引用,即GC Roots。

根可达算法原理

知道了什么是GC Roots那么根可达算法理解起来就相对来说会简单一些。GC Roots我们可以简单理解为和Java程序的生命周期强关联、和JVM生命周期强关联或者和当前线程强关联的一些对象。这些对象至少说在发生GC这一时刻是不应该被当成垃圾回收掉的,否则会影响程序的正常使用,因此,我们标记存活对象的时候从GC Roots开始,认为被GC Roots 引用或者间接引用的对象就是存活对象。因此,根可达算法的基本原理和流程如下:

  1. 初始根集合(Initial Roots): 根可达算法从程序的初始根集合开始,这些根是一组特殊的引用,如线程栈中的引用、静态变量、JNI(Java Native Interface)引用等。

  2. 标记阶段(Mark Phase): 算法通过追踪根引用,递归遍历对象图,标记所有可以从根引用访问到的对象。在这个过程中,被标记的对象被认为是可达的,而未被标记的对象被认为是不可达的。

  3. 标记-清除阶段(Mark-Sweep Phase): 在标记完成后,算法执行清除操作,即移除未被标记的对象。这些未被标记的对象被认为是不可达的,可以被垃圾回收器回收。这个阶段的目标是回收不再被程序使用的内存空间。

  4. 压缩(Compaction)或整理(Compaction): 在某些情况下,为了优化内存布局,可能会执行进一步的操作,如将存活对象整理到一起,以减少内存碎片。这个步骤通常与标记-清除阶段结合使用。

  5. 可选的再标记阶段(Optional Re-Mark Phase): 有些算法可能会在标记-清除后执行可选的再标记阶段,以处理在清除阶段可能发生的并发引用更新。这一步确保在垃圾回收过程中引用关系的一致性。

  6. 结束(Finish): 垃圾回收算法完成后,内存中只留下了可达对象,而不可达的对象已被清理。程序可以继续执行。

实际上来说,如CMS和G1之类比较流行的垃圾回收器都是采用的“三色标记”算法,而非直接采用的根可达算法来对垃圾进行标记的.

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

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

相关文章

python-windows10普通笔记本跑bert mrpc数据样例0.1.048

python-windows10普通笔记本跑bert mrpc数据样例0.1.000 背景参考章节获取数据下载bert模型下载bert代码windows10的cpu进行训练进行预测注意事项TODOLIST背景 看了介绍说可以在gpu或者tpu上去微调,当前没环境,所以先在windows10上跑一跑,看是否能顺利进行,目标就是训练的…

弱智吧”,人类抵御AI的最后防线

“写遗嘱的时候错过了deadline怎么办?” “怀念过去是不是在时间的长河里刻舟求剑?” “英语听力考试总是听到两个人在广播里唠嗑,怎么把那两个干扰我做题的人赶走?” 以上这些饱含哲学但好像又莫名其妙的问题,出自…

【2024算力大会分会 | SPIE独立出版 | 往届均已完成EI检索】2024云计算、性能计算与深度学习国际学术会议(CCPCDL 2024)

【2024算力大会分会 | SPIE出版】 2024云计算、性能计算与深度学习国际学术会议(CCPCDL 2024) 2024 International conference on Cloud Computing, Performance Computing and Deep Learning *CCPCDL往届均已完成EI检索,最快会后4个半月完成! 一、…

Huggingface-cli 登录最新版(2024)

安装Huggingface-cli pip install -U "huggingface_hub[cli]"设置好git的邮箱和用户名和huggingface的github账号一致 git config --global user.mail xxx git config --global user.name xxx登录 复制token,划红线的地方,在命令行中点击右…

SQL 数据库学习 Part 1

数据和信息 信息 信息是客观存在的,是关于现实世界事物的存在方式或运动状态 数据 数据是用来记录信息的可识别的符号,是信息的具体表现形式 数据和信息的联系 数据是信息的符号表示或载体信息则是数据的内涵,是对数据的语义解释 数据…

专业级中文AI文图创作:智源中英双语AltDiffusion开源

AIGC 如火如荼发展的当下,中文世界的创作者常有几大痛点: 思考英文Prompts准确表达的绞尽脑汁,翻译软件词不达意的尴尬,精细构思的 Prompts 在画面生成中找不到一丝痕迹,亦或面对文化误解中的“中国风”哭笑不得…… …

计算机操作系统基础知识:什么是虚拟机?虚拟机的分类有哪些?他们之间的区别是什么?

谈到虚拟机就必须谈谈为什么虚拟机会出现?它解决了哪些问题。 1.虚拟机出现的原因 为了解决传统虚拟机物理资源极大浪费,且希望在一台机器上运行多个应用,且他们之间不相互影响的问题。 下面开始正式介绍虚拟机: 1.虚拟机的定义…

【PX4-AutoPilot教程-TIPS】PX4加速度计陀螺仪滤波器参数设置

PX4加速度计陀螺仪滤波器参数设置 前期准备滤波前FFT图滤波后FFT图 环境: 日志分析软件 : Flight Review PX4 :1.13.0 前期准备 进行滤波器参数设置的前提是飞机简单调试过PID已经可以稳定起飞,开源飞控的很多默认参数是可以让飞机平稳起…

一款开源的图片/视频无损放大神器,本地可用!

哈喽,各位小伙伴们好,我是给大家带来各类黑科技与前沿资讯的小武。 要说无损放大图片/视频分辨率,就绕不开在github上开源的一个图像/视频恢复的实用算法——Real-ESRGAN,截止目前已斩获26.6k的Star量。 RealESRGAN-gui 软件介绍…

C++240611

2.编程题: 以下是一个简单的 比喻,将 多态概念 与 生活中 的 实际情况相联系: 比喻:动物园的讲解员和动物表演 想象一下你去了一家动物园,看到了许多不同种类的动物, 如狮子、大象、猴子等。现在&#xff…

冰蝎4.1webshell实验

1、基础环境 生成payload 2、default_xor_base64 HTTP 命令执行 chunked数据回包,48 3、default_xor_base64 HTTPS 命令执行 终端 文件管理 4、 default_aes https 虚拟终端 5、 default_aes http 虚拟终端

基于微信小程序的“最多跑一次”警务信息管理系统

作者主页:Java码库 主营内容:SpringBoot、Vue、SSM、HLMT、Jsp、PHP、Nodejs、Python、爬虫、数据可视化、小程序、安卓app等设计与开发。 收藏点赞不迷路 关注作者有好处 文末获取源码 技术选型 【后端】:Java 【框架】:ssm 【…

【安卓13 源码】Input子系统(2) - input系统与应用进程通信

点击手机屏幕,可以分发input 事件到对应的view,由上一节知道input 是运行在system 进程的,那应用进程与系统进程是如何通讯的呢,相信本文可以给到一点小小的答案。 先给个结论:应用在resume 的时候才去建立与input 服…

Rust学习06:使用CSDN的AI工具“C知道”分析代码错误

朋友们,我最近真的是在绝望的边缘了! Rust咋这么蓝涅! 资料咋这们少涅! 记得学Python的时候,基本上你遇到的所有问题都可以在书上或者网上找到答案,中文世界找不到那么在英文世界一定能找到答案。 我猜&…

intel 660P SSD 512GB测评

** intel 660P SSD 512GB测评 ** PCIE 3.0X4 支持NVME 1.3协议 固件版本号HPS0 顺序Read速度1843MB\s 顺序Write速度946MB\s 4K随机Read速度275MB\s 4K随机Write速度592MB\s H2缓内Write速度671MB\s H2缓外Write速度368MB\s H2全盘Read速度870MB\s HDtune全盘Read速度1853MB\…

ModbusTCP、TCP/IP都走网线,一样吗?

在现代通信技术中,Modbus/TCP和TCP/IP协议是两种广泛应用于工业自动化和网络通信领域的协议。尽管它们都运行在网线上,但它们在设计、结构和应用场景上有着明显的区别。 Modbus/TCP协议是什么 Modbus/TCP是一种基于TCP/IP的应用层协议,它是Mo…

gitLab批量下载有权限的项目

前言 参考 https://www.jianshu.com/p/b3d4e5cee835 适用于git私服拉取个人所涉及权限的代码,方便有多个项目权限的人快速拉取自己所有权限的代码。 默认生成目录结构与gitlab一致 步骤一:获取权限你的代码权限文件d 从gitlab私服生成所有你有权限的代码信息 …

DevExpress Data Binding

DevExpress数据感知控件与任何数据访问技术(ADO.NET、Entity Framework、XPO等)兼容,并且可以显示来自实现IList、IBindingList或ITypedList接口的任何数据源的数据。有关更多详细信息,请参阅这些帮助主题:传统数据绑定…

excel两个数据表格,怎样实现筛选的联动?

如图,想要通过处理器或者像素条件进行筛选,形成一个右边图2的对比表,如何实现实现联动显示呢? 这个在excel里可以借用数据透视表切片器来完成。步骤如下: 1.添加表 选中数据区域中任意一个单元格,点击 插…

Query传递的参数需不需要加注解?加什么?为什么有的时候要加有的时候不加?

Query传递过来的参数可以加,也可以不加注解。如果要加,是在传递的参数名和后端的变量名不一致的情况下,要加RequestParam如果传递过来的参数名和后端的变量名一致,则可以不加RequestParam。 传递过来的数据如果是通过 Query 方式…