内存管理:判断对象是否存活

news2024/11/24 15:49:45

引用计数算法

引用计数算法(Reference Counting)判断对象是否存活的基本思路是:在对象中添加一个引用计数器,每当有一个地方引用该对象时,计数器的值就加一;当引用失效时,计数器的值就减一;任何时刻计数器为零的对象就是不可能再被使用的对象。


客观地说,引用计数算法虽然占用了一些额外的内存空间来进行计数,但引用计数算法的原理简单,判定效率也很高,在大多数情况下它都是一个不错的算法。也有一些比较著名的应用案例, 例如微软 COM(Component Object Model)技术、使用 ActionScript3 的 FlashPlayer、Python 语言以及在游戏脚本领域得到许多应用的 Squirrel 中都使用了引用计数算法进行内存管理。

但是,在 Java 领域,至少主流的 Java 虚拟机里面都没有选用引用计数算法进行内存管理,主要原因是,这个看似简单的算法有很多例外情况要考虑,必须要配合大量的额外处理才能保证正确地工作,譬如单纯的引用计数就很难解决对象之间相互循环引用的问题。

举个简单的例子,请看代码清单 3-1 的 testGC() 方法:对象 objA 和 objB 都有字段 instance,赋值令 objA.instance=objB 及 objB.instance=objA,除此之外,这两个对象再无任何引用,实际上这两个对象已经不可能再被访问,但是因为它们互相引用着对方, 导致它们的引用计数都不为零,引用计数算法也就无法回收它们。

代码清单 3-1 引用计数算法的缺陷

/**
 * testGC()方法执行后, objA和objB会不会被GC呢?
 *
 * @author zzm
 */
public class ReferenceCountingGC {
    public Object instance = null;
    private static final int _1MB = 1024 * 1024;
    /**
     * 这个成员属性的唯一意义就是占点内存, 以便能在GC日志中看清楚是否有回收过
     */
    private byte[] bigSize = new byte[2 * _1MB];

    public static void testGC() {
        ReferenceCountingGC objA = new ReferenceCountingGC();
        ReferenceCountingGC objB = new ReferenceCountingGC();
        objA.instance = objB;
        objB.instance = objA;
        objA = null;
        objB = null;
		// 假设在这行发生GC, objA和objB是否能被回收?
        System.gc();
    }
}

可达性分析算法

当前主流的商用程序语言(Java、C#,上溯至古老的 Lisp)的内存管理子系统,都是通过可达性分析(Reachability Analysis)算法来判断对象是否存活。

可达性分析算法判断对象是否存活的基本思路是:通过一系列被称为 “GC Roots” 的根对象作为起始节点集,从这些节点开始,根据引用关系向下搜索,搜索过程所走过的路径被称为 “引用链”(Reference Chain),如果某个对象到 GC Roots 间没有任何引用链相连(用图论的话来说就是从 GC Roots 到这个对象不可达)时,则证明此对象是不可能再被使用的对象。

如下图所示,对象 object 5、object 6、object 7 虽然互有关联,但是它们到 GC Roots 是不可达的,因此它们将会被判定为是可回收的对象。

image-20230222100921648.png

在 Java 技术体系里面,固定可作为 GC Roots 的对象包括以下几种:

  • Java 虚拟机栈(栈帧中的本地变量表) 中引用的对象,譬如各个线程调用的方法堆栈中使用到的参数变量(方法定义时声明的变量)引用的对象、局部变量(定义在方法中的变量)引用的对象、临时对象(没有变量引用的对象)等。

  • 本地方法栈中 JNI(即通常所说的 Native 方法)引用的对象(非 Java 代码中的对象)。

  • 方法区中引用的对象:

    • 方法区中类的静态属性(static 关键字)引用的对象,譬如 Java 类的引用类型静态变量。
    • 方法区中常量(static 和 final 关键字)引用的对象,譬如字符串常量池(String Table)里的引用。
  • 所有被同步锁(synchronized 关键字)持有的对象。

  • Java 虚拟机内部的引用,如基本数据类型对应的 Class 对象,一些常驻的异常对象(比如 NullPointExcepiton、 OutOfMemoryError)等,还有系统类加载器。

  • 反映 Java 虚拟机内部情况的 JMXBean、JVMTI 中注册的回调、本地代码缓存等。

除了这些固定的 GC Roots 集合以外,根据用户所选用的垃圾收集器以及当前回收的内存区域不同,还可以有其他对象 “临时性” 地加入,共同构成完整的 GC Roots 集合。譬如后文将会提到的分代收集和局部回收(Partial GC),如果只针对 Java 堆中某一块区域发起垃圾收集时(如最典型的只针对新生代的垃圾收集),必须考虑到内存区域是虚拟机自己的实现细节(在用户视角里任何内存区域都是不可见的),更不是孤立封闭的,所以某个区域里的对象完全有可能被位于堆中其他区域的对象所引用,这个时候就需要将这些关联区域的对象也一并加入 GC Roots 集合中去,这样才能保证可达性分析的正确性。 

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

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

相关文章

Vector - CAPL - 诊断模块函数(TP层配置)

诊断TP层常见参数值 网络层定时参数的放置 常见的时间参数在诊断数据交互中的位置,后续会专门出一期关于ISO 15765-2的介绍。 CAPL对于此类函数介绍 CanTpGetTimeoutAr & CanTpGetTimeoutAr long CanTpGetTimeoutAr(long connHandle); long CanTpSetTimeoutAr(…

RabbitMQ 教程 | RabbitMQ 简介

👨🏻‍💻 热爱摄影的程序员 👨🏻‍🎨 喜欢编码的设计师 🧕🏻 擅长设计的剪辑师 🧑🏻‍🏫 一位高冷无情的编码爱好者 大家好,我是 DevO…

充分了解java阻塞队列机制

多线程基础 1.阻塞队列1.1 什么是 阻塞队列1.2 阻塞队列的特点 1.3 阻塞队列常用方法1.3.1 抛出异常:add、remove、element1.3.2 返回结果但是不抛出异常offer、poll、peek1.3.3 阻塞put和take1.3.4 小结 1.4 常见的阻塞队列1.4.1 ArrayListBlockingQueue1.4.2 LinkedBlockingQ…

国标GB28181协议视频平台EasyCVR修改录像计划等待时间较长的原因排查与解决

音视频流媒体视频平台EasyCVR拓展性强,视频能力丰富,具体可实现视频监控直播、视频轮播、视频录像、云存储、回放与检索、智能告警、服务器集群、语音对讲、云台控制、电子地图、H.265自动转码H.264、平台级联等。为了便于用户二次开发、调用与集成&…

【PMP】有没有项目经理能看得懂这九张图?求挑战

这九张图,全是圈圈我的肺腑之言啊!谁痛谁知道! 做技术时,就想着30岁就转管理,管理岗位赚得多,结果发现全是烟雾弹。 做技术和代码打交道,做管理跟人打交道。天天开不完的会、说不完的话&#xf…

https证书怎么选择?

https证书即SSL数字证书,是遵守 SSL 协议的一种数字证书,由全球信任的证书颁发机构 (CA) 验证服务器身份后颁发,将 SSL 证书安装在网站服务器上,会激活挂锁和 https 协议。SSL 证书解决了网民登录网站的信任问题,网民可…

Java使用hive连接kyuubi

一、Maven依赖 <dependency><groupId>org.apache.hive</groupId><artifactId>hive-jdbc</artifactId><version>2.3.9</version> </dependency> 二、相关配置信息 驱动类&#xff1a;org.apache.hive.jdbc.HiveDriver连接UR…

HDMI接口需注意的PCB可制造性设计问题

高清多媒体接口(High Definition Multimedia Interface)简称HDMI&#xff0c;是一种全数字化视频和声音发送接口&#xff0c;可以同时发送未压缩的视频及音频信号&#xff0c;且发送时采用同一条线材&#xff0c;大大简化了系统线路的安装难度&#xff0c;所以应用非常广泛&…

ubuntu初始化/修改root密码

1.登录ubuntu后&#xff0c;使用sudo passwd root命令&#xff0c;进行root密码的初始化/修改&#xff0c;注&#xff1a;这里需要保证两次输入的密码都是同一个&#xff0c;才可成功 ubuntugt-ubuntu22-04-cmd-v1-0-32gb-100m:~/ocr$ sudo passwd root New password: Retype…

《2023中国开发者调查报告》探索2023中国开发者的技术创新与挑战:AIoT、云原生、国产数据库等领域的发展与前景

&#x1f337;&#x1f341; 博主猫头虎 带您 Go to New World.✨&#x1f341; &#x1f984; 博客首页——猫头虎的博客&#x1f390; &#x1f433;《面试题大全专栏》 文章图文并茂&#x1f995;生动形象&#x1f996;简单易学&#xff01;欢迎大家来踩踩~&#x1f33a; &a…

2023最新Windows安装配置Redis教程,嘎嘎详细

虽然 Redis 官方网站没有提供 Windows 版的安装包&#xff0c;但可以通过 GitHub 来下载 Windows 版 Redis 安装包&#xff0c;下载地址&#xff1a;https://github.com/tporadowski/redis/releases。 注意&#xff1a;Windows 安装包是某位民间“大神”根据 Redis 源码改造的&…

mybatisPlus之通用枚举及字段类型处理器

目录 通用枚举 为什么需要枚举类 EnumValue 具体使用 字段类型处理器 为什么需要字段类型处理器 具体使用 通用枚举 为什么需要枚举类 类的对象只有有限个&#xff0c;确定的。举例如下&#xff1a; 星期&#xff1a;Monday(星期一)、......、Sunday(星期天)性别&#x…

SentencePiece android ndk编译

LLaMa等LLM语言模型一般使用SentencePiece tokenizer&#xff0c;在端侧部署需要编译和使用其c版本。 在安卓平台使用NDK编译 CMakeLists.txt需要进行一些修改&#xff1a; src/CMakeLists.txt如下位置加上log依赖&#xff0c;否则提示android log相关符号不存在。 此外&…

【云原生技术】高效、灵活、易于使用的低代码快速开发平台源码

PaaS低代码快速开发平台是一种快速开发应用系统的工具&#xff0c;用户通过少量代码甚至不写代码就可以快速构建出各种应用系统。 随着信息化技术的发展&#xff0c;企业对信息化开发的需求正在逐渐改变&#xff0c;传统的定制开发已经无法满足企业需求。低代码开发平台&#x…

Michael.W基于Foundry精读Openzeppelin第13期——Checkpoints.sol

Michael.W基于Foundry精读Openzeppelin第13期——Checkpoints.sol 0. 版本0.1 Checkpoints.sol 1. 目标合约2. 代码精读2.1 History体系2.1.1 push(History storage self, uint256 value) && push(History storage self, function(uint256, uint256) view returns (uin…

Windows10下NI板卡驱动安装

文章目录 一. NI&#xff08;National Instruments 美国国家仪器有限公司&#xff09;介绍二. NI Package Manager软件说明 一. NI&#xff08;National Instruments 美国国家仪器有限公司&#xff09;介绍 官网地址: https://www.ni.com/zh-cn/solutions.html?category&…

基于SpringBoot+Vue的实习管理系统设计与实现(源码+LW+部署文档等)

博主介绍&#xff1a; 大家好&#xff0c;我是一名在Java圈混迹十余年的程序员&#xff0c;精通Java编程语言&#xff0c;同时也熟练掌握微信小程序、Python和Android等技术&#xff0c;能够为大家提供全方位的技术支持和交流。 我擅长在JavaWeb、SSH、SSM、SpringBoot等框架…

python pip更新

python pip更新 D:\python>python -m pip list Package Version ---------- ------- pip 23.1.2 setuptools 65.5.0[notice] A new release of pip is available: 23.1.2 -> 23.2.1 [notice] To update, run: python.exe -m pip install --upgrade pipD:\pyt…

Qt完成文本转换为语音播报与保存(系统内置语音引擎)

一、前言 在当今数字化社会,人们对于交互式应用程序的需求越来越高。除了传统的图形用户界面,语音交互也成为了一种流行的交互方式。在这种情况下,将文本转换为语音成为了一项重要的技术,它可以为用户提供更加人性化和便捷的交互方式。在此背景下,Qt提供了QTextToSpeech类…

LeetCode·每日一题·2500. 删除每行中的最大值·模拟

作者&#xff1a;小迅 链接&#xff1a;https://leetcode.cn/problems/delete-greatest-value-in-each-row/solutions/2360713/mo-ni-zhu-shi-chao-ji-xiang-xi-by-xun-ge-rhmz/ 来源&#xff1a;力扣&#xff08;LeetCode&#xff09; 著作权归作者所有。商业转载请联系作者获…