垃圾回收 - 引用计数法

news2024/11/28 8:47:09

GC原本是一种“释放怎么都无法被引用的对象的机制”。那么人们自然而然就会想到,可以让所有对象事先记录下“有多少程序引用了自己”。让各对象知道自己的“人气指数”,从而让没有人气的对象自己消失,这就是引用计数法。

1、计数器

计数器表示的是对象的人气指数,也就是有多少程序引用了这个对象。计数器是无符号的整数
在这里插入图片描述
1.1计数器的增减
在GC-标记清除算法的其他算法中,没有分块时mutator会调用下面这样的函数,启动GC分配空闲的内存空间。

garbage_collect(){
	.....
}

然而在引用计数法中并没有mutator明确启动GC的语句,引用计数法与mutator的执行密切相关,他在mutator的处理过程中通过增减计数器的值来进行内存管理。这涉及到new_obj()函数和update_ptr()函数

1.2 new_obj()函数

new_obj(size){
	obj = pickup_chunk(size,$free_list)
	if(obj == NULL) allocation_fail()
	else
		obj.ref_cnt = 1
		return obj
}

1.3 update_ptr()函数
该函数用于更新指针ptr,使其指向对象obj,同时进行计数器值的增减。

update_ptr(ptr,obj){
	inc_ref_cnt(obj)
	dec_ref_cnt(*ptr)
	*ptr = obj
}

inc_ref_cnt(obj){
	obj.ref_cnt ++;
}

dec_ref_cnt(obj){
	obj.ref_cnt --;
	if(obj.ref_cnt == 0)
		for(child : children(obj))
			dec_ref_cnt(*child)
		reclaim(obj)
}

该程序具体进行的是以下2项操作:

  • 对指针ptr新引用的对象obj的计数器进行增量操作
  • 对指针ptr之前引用的对象*ptr的计数器进行减量操作

在变更数组元素等的时候会进行指针的更新。通过更新指针,可能会产生没有被任何程序引用的的垃圾对象。引用计数法会监督在更新指针的时候是否有产生垃圾,从而在产生垃圾的时候立即将其回收。

2、优缺点

2.1优点

  • 可即刻回收垃圾
  • 最大暂停时间短
  • 没有必要沿着指针查找。

2.2缺点

  • 计数器值的增减处理繁重
  • 计数器需要占用很多位
  • 实现繁琐复杂
  • 循环引用无法回收

3、延迟引用计数法

因为引用计数法中计数器值的增减处理繁重。于是就产生了延迟引用计数法。计数器增减处理繁重的原因之一是从根的引用变化频繁,因此我们就让从根引用的指针的变换不反映在计数器上。比如我们把重写全局变量指针的update_ptr($ptr,obj)改写成*ptr = obj。
这样一来,即使频繁重写堆中对象的引用关系,对象的计数器值也不会有所变化。但是这样内存管理还是不能顺利进行。因为引用没有反应在计数器上,所以各个对象的计数器没有正确表示出对象本身被引用数。于是就有可能发生对象仍在活动但却被错当成垃圾回收的情况。
在这里插入图片描述
于是,我们在延迟引用计数法中使用ZCT(Zero Count Table),他会事先记录下计数器值在dec_ref_cnt()函数作用下变为0的对象。
在这里插入图片描述
因为计数器值为0的对象不一定都是垃圾,所以暂时先将这些对象保留。

优点:通过延迟减轻了因根引用频繁发生变化导致的计数器增减所带来的额外负担。
缺点:为了延迟计数器的增减,垃圾不能立马回收,导致垃圾压迫成堆,我们也就失去了引用计数法的优点-可即刻回收垃圾。

4、Sticky引用计数法

在引用计数法中,我们有必要研究一件事,那就是要为计数器设置多大的位宽,假设为了反映所有引用,计数器需要一个字(32位机器就是32位)的空间。但是这样回大量消耗内存空间。比如2个字的对象就要附加一个字的计数器,也就是说计数器害的对象所占空间增大了1.5倍
在这里插入图片描述
对此我们有个方法,那就是用来减少计数器位宽的“Sticky引用计数法"。举个例子,我们假设用于计数器的位数为5位,那么这种计数器最多只能数到2的5次方减1,就是31个引用数。如果此对象被大于31个引用对象引用,那么计数器就会溢出。针对计数器溢出,需要暂停堆计数器的管理,对付这种对象,我们主要有两种方法:

4.1、什么都不做
对于计数器溢出的对象,我们可以这样处理:不再增减计数器的值,就把它放着。但是这样一来,即使这个对象成了垃圾(引用次数为0)也不能将其回收,这样就白白浪费了内存空间。

4.2、使用标记清除算法处理
在适当的时候使用标记清除算法来充当引用计数法的后援。这样做的优点是在计数器溢出后即使成了垃圾,程序还是能够回收它,并且还可以回收循环的垃圾。

5、1位引用计数法

1位引用计数法是Stick的一个极端例子,就是计数器的大小只有一位,瞬间就会溢出。

6、部分标记清除法

之前已经讲过,引用计数法存在的一大问题就是不能回收循环的垃圾。这是引用计数法的一大特色,用GC标记清除算法就不会有这种问题。那么我们自然会想到,只要跟之前使用延迟引用计数法时一样,利用GC 标记清除算法不就好了吗?也就是说,可以采用一般情况下执行引用计数法,在某个时刻启动 GC 标记清除算法的方法。

6.1前提
在部分标记清除算法中,对象会被涂成4种颜色来进行管理:

颜色含义表示
绝对不是垃圾的对象(对象产生时的初始颜色)00
绝对是垃圾的颜色01
搜索完毕的对象10
阴影可能是循环垃圾的对象11

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

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

相关文章

【Unity基础】1.项目搭建与视图编辑

【Unity基础】1.项目搭建与视图编辑 大家好,我是Lampard~~ 欢迎来到Unity基础系列博客,终于要开始写基础系列的博客了,前两篇的内容基本上与入门系列相同,如果有紧跟入门系列的同学可以直接从第三篇文章开始看 好了话不多说我们开…

Java切换到Kotlin,Crash率上升了?

前言 最近对一个Java写的老项目进行了部分重构,测试过程中波澜不惊,顺利上线后几天通过APM平台查看发现Crash率上升了,查看堆栈定位到NPE类型的Crash,大部分发生在Java调用Kotlin的函数里,本篇将会分析具体的场景以及…

ORB-SLAM3复现过程中遇到的问题及解决办法

在复现过程中遇到的问题的解决过程 1. 版本检查1.1 Opencv版本的检测1.2 Eigen版本的检测1.3 查看Python版本1.4 其他 2. 编译过程中遇到的问题及解决办法2.1 ./build.sh遇到的问题2.2 ./build_ros.sh遇到的问题 因为环境比较干净,所以遇到的问题相对少一些&#xf…

ARM 汇编基础知识

1.为什么学习汇编? 我们在进行嵌入式 Linux 开发的时候是绝对要掌握基本的 ARM 汇编,因为 Cortex-A 芯片一 上电 SP 指针还没初始化, C 环境还没准备好,所以肯定不能运行 C 代码,必须先用汇编语言设置好 C 环境…

【python】实现积分

借助sympy.integrate() 符号运算库,所以里面的exp(),sin()等都要使用sympy库中的函数,如果使用numpy库中的函数时没用的。 import sympy as sp import numpy as np x sp.symbols("x") print(sp.integrate(sp.exp(-x**2), (x, -s…

企业数据加密软件——「天锐绿盾」

「天锐绿盾」是一款企业数据加密软件,主要用于防止企业计算机信息被破坏、丢失和泄密。该软件采用文件过滤驱动实现透明加解密,对用户完全透明,不影响用户操作习惯。 PC访问地址: isite.baidu.com/site/wjz012xr/2eae091d-1b97-4…

makefile开发应用程序的一个通用模板

下面是一个通用的 Makefile 模板,用于开发 C 语言应用程序: # 编译器设置 CC gcc CFLAGS -Wall -Wextra -stdc99# 可执行文件名 TARGET your_program# 源文件和对象文件 SRCS main.c file1.c file2.c OBJS $(SRCS:.c.o)# 默认目标 all: $(TARGET)#…

buildroot修改内核防止清理重新加载办法

当你使用 Buildroot 构建 Linux 内核时,如果对内核文件进行了手动修改,重新执行 Buildroot 的构建过程将会覆盖你所做的修改。这是因为 Buildroot会根据配置重新下载、提取和编译内核。 为了避免在重新构建时覆盖你的修改,可以采取以下两种方…

减量时代下,伊利金领冠DTB新模式凭什么成为母婴行业“破局之道”?

穷则变,变则通,通则久。 当下,许多行业正在穿越不确定性周期,增长放缓成为常态。如何通过创新应对变局,进而实现长期主义,成为摆在所有行业和企业面前的课题。 众多行业中,婴配粉市场的不确定…

lv3 嵌入式开发-3 linux shell命令(文件搜索、文件处理、压缩)

目录 1 查看文件相关命令 1.1 常用命令 1.2 硬链接和软链接 2 文件搜索相关命令 2.1 查找文件命令 2.2 查找文件内容命令 2.3 其他相关命令 3 文件处理相关命令 3.1 cut 3.2 sed 过滤 3.3 awk 匹配 4 解压缩相关命令 4.1 解压缩文件的意义 4.2 解压缩相关命令 1 …

推荐个一行代码的Python可视化神器

学过Python数据分析的朋友都知道,在可视化的工具中,有很多优秀的三方库,比如matplotlib,seaborn,plotly,Boken,pyecharts等等。这些可视化库都有自己的特点,在实际应用中也广为大家使…

数据结构(Java实现)-反射、枚举以及lambda表达式

Java的反射(reflection)机制是在运行状态中,对于任意一个类,都能够知道这个类的所有属性和方法;对于任意一个对象,都能够调用它的任意方法和属性,既然能拿到那么,我们就可以修改部分…

内网隧道代理技术(二十一)之 CS工具自带中转技术上线不出网机器

CS工具自带上线不出网机器 如图A区域存在一台中转机器,这台机器可以出网,这种是最常见的情况。我们在渗透测试的过程中经常是拿下一台边缘机器,其有多块网卡,边缘机器可以访问内网机器,内网机器都不出网。这种情况下拿这个边缘机器做中转,就可以使用CS工具自带上线不出网…

shiro550漏洞分析

准备工作 启动该项目 可以看到没有登录时候,cookie中没有rememberme字段 登录时候 当账号密码输入正确时候 登录后存在该字段 shiro特征: 未登陆的情况下,请求包的cookie中没有rememberMe字段,返回包set-Cookie⾥也没有del…

JMeter测试工具

JMeter测试工具 1、下载地址: https://downloads.apache.org/jmeter/binaries/ https://downloads.apache.org/jmeter/binaries/2、启动 解压: 点击bin目录下的jmeter.bat就可以运行 jmeter.bat3、流控规则测试

蓝牙发展现状

目录 一、产品分类1、Bluetooth经典2、Bluetooth低能耗(LE)3、二者差异 二、出货量三、未来需要加强的方向四、技术行业细分五、学习资料1、蓝牙官网2、大神博客——于忠军 一、产品分类 1、Bluetooth经典 Bluetooth Classic无线电,也被称为Bluetooth 基本速率/增强…

EasyExcel导出模板实现下拉选(解决下拉超过50个限制)

学习地址:https://d9bp4nr5ye.feishu.cn/wiki/O3obweIbgi2Rk1ksXJncpClTnAfB站视频:https://www.bilibili.com/video/BV1H34y1T7Lm 先来看看最终实现效果,如果效果是你想要的,再看看实现逻辑。 EasyExcel本身是支持设置下拉校验的…

大学物理 之 安培环路定理

文章目录 前言什么是安培环路定理安培环路定理有什么作用 深入了解深入学习 前言 什么是安培环路定理 安培环路定理的物理意义在于描述了电流和磁场之间的相互作用,以及如何在一个封闭的回路中分析这种相互作用。 简单的来说 , 用环路定理来解决在磁场中B对任意封…

教你如何让iPhone电池更健康,不容错过的10个技巧

iPhone是一款功能强大的设备,但与许多电子产品一样,它需要一些维护才能确保正常工作。就像一艘可以永远航行的船,只要人们愿意维护它,只要你保持电池健康,你的iPhone就会继续工作。 以下是为什么维护iPhone电池至关重要,以及如何做到这一点,让你的设备使用更长时间。 …

数据结构 -作用及基本概念

为什么要使用数据结构 学习数据结构是计算机科学和软件工程领域中非常重要的一门课程。以下是学习数据结构的几个重要原因: 组织和管理数据:数据结构提供了一种组织和管理数据的方式。通过学习不同的数据结构,你可以了解如何有效地存储和操作…