如何判断对象是否该被回收(引用计数法、可达性分析算法)

news2024/12/30 3:55:34

👨‍💻个人主页: 才疏学浅的木子
🙇‍♂️ 本人也在学习阶段如若发现问题,请告知非常感谢 🙇‍♂️
📒 本文来自专栏: JVM
🌈 算法类型Hot100题 🌈
❤️ 支持我:👍点赞 🌹收藏 🤟关注

文章目录

  • 概述
    • 垃圾收集器需要完成的三件事
    • 那些需要进行GC
  • 如何判断对象是否该被回收?
    • 引用计数法
    • 可达性分析算法
    • 引用
    • 生存还是死亡
    • 回收方法区

概述

垃圾收集器需要完成的三件事

那些内存需要回收?
什么时候回收?
如何回收?

那些需要进行GC

程序计数器、虚拟机栈、本地方法栈3个区域随线程而生,随线程灭而灭,栈中的栈帧随着方法的进入和退出有条不紊的进行出栈和入栈操作。每一个栈帧中分配多少内存基本上是在类结构确定下来时就已知(尽管在运行期间会由即时编译器进行一些优化,但在基于概念模型的讨论里,大体上可以认为是已知的),因此这几个区域内存的分配和回收都具备确定性,在这几个区域内就不需要过多考虑回收的问题,当方法结束或者线程结束时,内存自然就随着回收了
Java堆和方法区这两个区域则有着很显著的不确定性:一个接口的多个实现类需要的内存可能会不一样,一个方法所执行的不同条件分支所需要的内存也可能不一样,只有处于运行期间,我们才能知道这个程序究竟会创建那些对象。

如何判断对象是否该被回收?

引用计数法

在对象里面添加一个引用计数器,每当有一个对象引用它时,计数器值就加一;每当引用失效,计数器的值就减一;任何时刻计数器为零的对象就是不可能再被使用的

/**
 * @className: JVM_1
 * @description: 测试JVM是否使用引用计数法
 * @author: 热爱生活の李
 * @since: 2022/5/20 14:52
 */
public class JVM_1 {
    public Object instance = null;
    private static final int _1MB = 1024 * 1024;

    public static void main(String[] args) {
        JVM_1 objectA = new JVM_1();
        JVM_1 onjectB = new JVM_1();
        objectA.instance = onjectB;
        onjectB.instance = objectA;

        objectA = null;
        onjectB = null;
        System.gc();
    }
}

在这里插入图片描述

添加GC日志打印
运行配置里加VM option
参数为 -XX:+PrintGCDetails

缺点
可能会造成循环引用,导致无法回收,例如:上面对象objectA和objectB都有字段instance,objectA.instance = objectB,objectB.instance = objectA,除此之外,这两个对象再无其他任何引用,实际上这两个对象不可能被访问,但是他们互相引用对方,导致引用计数器不为0,就无法回收它们。

可达性分析算法

通过一系列称为“ GC Roots ” 的根对象作为起始节点集,从这些节点开始,根据引用关系向下搜索,搜索过程所走过的路径称为“ 引用链 ” ,如果某个对象到GC Roots 间没有任何链相连,或者用图论的话来说就是从GC Roots到这个对象不可达时,则证明对象不可能再被使用

在这里插入图片描述

那些可以作为GC Roots对象

固定作为GC Roots
1、在虚拟机栈中引用的对象(各个线程被调用的方法栈中的参数、局部变量、临时变量)
2、在方法区中类静态属性引用的对象(Java类的引用类型静态变量)
3、在方法区常量引用的对象(字符串常量池String Table的引用)
4、在本地方法栈中引用的对象(Native方法)
5、Java虚拟机内部的引用(基本数据类型对应的Class对象,一些常驻的异常对象比如NullPointException,还有系统类加载器)
6、所有被同步锁(synchronized关键字)持有的对象
7、反映Java虚拟机内部情况的JMXBean、JVMTL注册的回调、本地代码缓存等

根据用户所选择的垃圾收集器以及当前回收的内存区域不同,还可以用其他对象"临时性"地加入

引用

Java对引用的概念进行了扩充,将引用分为强引用(Strongly Reference)、软引用(Soft Reference)、弱引用(Weak Reference)和虚引用(Phantom Reference)

强引用: 指在程序代码之间存在的引用赋值,即类型Object obj = new Object() 这种引用关系。无论任何关系下,只要强引用关系还存在,垃圾收集器就不会回收掉被引用的对象
软引用: 用来描述一些还有用,但非必须的对象。只被软引用关联着的对象,在系统将要发生内存溢出异常前,会把这些对象列进回收范围之中进行第二次回收,如过这次回收还是没有足够的内存,才会抛出内存溢出异常。
弱引用: 用来描述那些非必要对象,但是它的强度比软引用更弱一些,关联的对象只能生存到下一次垃圾收集为止。当垃圾收集器开始工作,无论当前内存是否足够,都会回收掉只被弱引用关联的对象
虚引用: 最弱的一种引用关系。一个对象是否有虚引用的存在,完全不会对其生存时间构成影响,也无法通过虚引用来取得一个对象实列。为一个对象设置虚引用关联的唯一目的只是为了能在这个对象被收集器回收的时候收到一个系统通知。

生存还是死亡

即使是在可达性分析算法中判断为不可达的对象也不是非死不可,要真正宣告一个对象死亡,至少要经历两次标记过程。

在这里插入图片描述

package JVM;
/**
 * @className: JVM_2
 * @description: 测试finalize()方法
 * @author: 热爱生活の李
 * @since: 2022/5/20 15:08
 */
public class JVM_2 {
    public static JVM_2 instance = null;
    @Override
    protected void finalize() throws Throwable {
        super.finalize();
        System.out.println("finalize 方法执行了 !!!");
        JVM_2.instance = this;
    }

    public static void main(String[] args) throws InterruptedException {
        instance = new JVM_2();
        instance = null;
        System.gc();
        // finalizer方法优先级很低
        Thread.sleep(5000);
        if(instance != null){
            System.out.println("我还活着 !!!");
        }else {
            System.out.println("我死了 !!!");
        }
        instance = null;
        System.gc();
        Thread.sleep(5000);
        if(instance != null){
            System.out.println("我还活着 !!!");
        }else {
            System.out.println("我死了 !!!");
        }
    }
}

在这里插入图片描述

finalize()方法只会被调用一次

回收方法区

方法区的垃圾收集主要回收两部分内容:废弃的常量和不再使用的类型

回收废弃的常量
假如一个字符串“Java” 曾经进入常量池,但是当前系统又没有任何一个字符串对象的值是“Java”,换句话说已经没有任何字符串对象引用常量池中的”Java“常量,且虚拟机中也没有其他地方引用这个字面量。如果这时发生内存回收,而且垃圾收集器判断有必要的话,这个”Java“常量就会被清理出常量池。常量池中其他类(接口)、方法、字段的符号引用也与此类似

回收类型的判断条件
1、该类的所有实例化都已经被回收,也就是Java堆中不存在该类及其任何派生子类的实例
2、加载该类的类加载器已经被回收
3、该类对应的java.lang.Class对象没有在任何地方被引用,无法在任何地方通过反射访问该类的方法

Java虚拟机被允许对满足上述三个条件的无用类进行回收,这里说的仅仅是被允许,而并不是和对象一样,没有引用就被必然被回收。
关于是否要对类型进行回收,HotSpot虚拟机提供了 -Xnoclassgc 参数进行控制,还可以使用 -verbose:class 以及 -XX:+TraceClassLoading、-XX:TraceClassUnLoading 查看类加载和卸载信息

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

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

相关文章

计算机的应用领域

文章目录计算机的应用领域1、商业2、银行业3、保险行业4、教育行业5、市场营销6、卫生保健7、工程设计8、军事9、通讯10、政府计算机的应用领域 本节,我将带领您了解计算机在各个领域的应用。 1、商业 计算机的功能丰富,极高的计算能力,计…

sqli-labs/Less-56

这一关的欢迎界面提示我们还是以id作为注入点 我们仍然有14次尝试机会 首先我们还是先来判断一下是否属于数字型注入 输入如下 id1 and 12 回显如下 正确回显 属于字符型 接着输入1 查看回显 这个回显说明两件事情 一个是我们后面不能使用报错注入进行注入了 一个是我们这个…

Elasticsearch:使用反向地理编码在地图上显示自定义区域统计数据

在实际的许多应用中,我们可能并不一定按照行政区来进行划分区域,比如我们常说江浙一代,我们可以理解江苏和浙江这两个省合在一起,而不是把它们分开。我们有时也说长江三角区,它可能是跨几个省市的一个区域,…

每隔一段时间自动敲键盘的的vbs脚本

1. 上代码 set wscreateobject("wscript.shell") do ws.sendkeys "{TAB}" WScript.Sleep Int(6 *Rnd1)*1000 loop2. 代码解释 每隔1~6秒,按一次TAB键 2.1 循环执行操作代码 do ....操作..... loop2.2 按下Tab键 ws.sendkeys "{TAB}" 即…

HTML5期末大作业商城网页设计与实:(手表 3页)HTML+CSS

⛵ 源码获取 文末联系 ✈ Web前端开发技术 描述 网页设计题材,DIVCSS 布局制作,HTMLCSS网页设计期末课程大作业 | 在线商城购物 | 水果商城 | 商城系统建设 | 多平台移动商城 | H5微商城购物商城项目 | HTML期末大学生网页设计作业 HTML:结构 CSS&#…

python中字典的循环遍历的方式

python开发中经常会用到对于字典、列表等数据的循环遍历,但是python中对于字典的遍历对于很多初学者来讲非常陌生,今天就来讲一下python中字典的循环遍历的两种方式。 注意: python2和python3中,下面两种方法都是通用的。 1、只…

两种数据提取框架的比较(scrapy和webmagic)

背景: 最近北京疫情有点严重,状态是居家办公,又是买菜做饭又是核酸检测心情是无比的烦躁还总是会议,无需发言的会议就边听边写写csdn记录一下。这几天在用Java写一个数据抓取的程序,用于数据分析等等。第一是因为原项目…

十二、虚拟 DOM 和 render() 函数(2)

本章概要 用普通 JavaScript 代替模板功能 v-if 和 v-forv-modelv-on事件和按键修饰符插槽 JSX实例:帖子列表 12.3 用普通 JavaScript 代替模板功能 原先在模板中可以使用的一些功能在 render() 函数中没有再提供,需要自己编写 JavaScript 代码来实现…

docker-Cgroups的资源限制

一、Cgroup的介绍 cgroups,是一个非常强大的linux内核工具,他不仅可以限制被namespace 隔离起来的资源,还可以 为资源设置权重、计算使用量、操控进程启停等等。所以cgroups (Control groups) 实现了对资源的配额和度量。 cpu时间片的概念 …

atoi函数的介绍和模拟实现

今天我来介绍atoi函数和模拟实现atoi函数。 目录atoi和与其功能相似的函数的介绍atoi函数的模拟实现atoi和与其功能相似的函数的介绍 atoi函数是一个将字符串转换为整数值的函数。 由msdn查询可以得知,atoi函数的返回类型是int类型,参数类型是const ch…

用于不同功率的模块式TEC半导体致冷器超高精度温度控制装置

摘要:针对目前TEC半导体制冷器温控装置对高精度、模块化、可编程和远程控制等方面的技术需求,本文提出了一种高性价比的解决方案。解决方案的具体内容是采用模块式结构,以24位AD和16位DA超高精度PID控制器作为基础单元,采用分立模…

不调参,免训练,VisionBank AI OCR新功能升级上线!

应用背景 OCR字符识别,是指对部件或产品上刻印的字符进行确认、辨别、判定的检测识别。此项技术目前已广泛应用于工业自动化生产的产品质量管理环节当中,企业通过为机器视觉检测设备安装OCR系统,快速完成对产品生产日期、保质期、生产批号、…

红色荧光TAMRA alkyne 5-isomer,945928-17-6,5四甲基罗丹明-炔基

TAMRA alkyne,5-isomer反应原理: 红色荧光四甲基罗丹明炔烃可通过铜催化的点击反应与叠氮化合物反应。点击化学的代表反应为铜催化的叠氮-炔基Husigen环加成反应(Copper-Catalyzed Azide–Alkyne Cycloaddition)。点击化学的概念对化学合成领…

线性二分类——机器学习

目录 一、算法思想 二、算法原理 三、算法分析 四、源程序代码 五、运行结果及分析 六、总结 一、算法思想 (1)二分类:表示分类任务有两个类别,比如我们想识别图片中是不是狗,也就是说,训练一个分类器,…

如何使用云服务器搭配宝塔面板搭建Z-blog个人博客系统

之前写过使用过WordPress和Typecho搭建个人博客网站的方法,这篇文章将使用Z-blog搭建个人博客系统,Z-blog相当于WordPress而言,更加小巧,但是依然有着强大的功能,以及丰富的主题和插件,因此也值得很多用户选…

数字图像处理均衡化、规定化例题及解题思路

目录 均衡化 规定化 均衡化 前置知识: rk:表示灰度级 nk:表示第k个灰度级出现的个数 sk:表示用变换函数公式计算映射后的灰度级sk 变换函数公式: 例题: 1.列表写出图像直方图均衡化的过程 2.画出均衡化以后的图像 3.画出原始图像直方图…

如何给PDF解密?建议收藏这些方法

我们在传输接收文件的时候,经常都是以PDF格式进行的,因为PDF格式具有很强的稳定性。那小伙伴们平时接收的时候,会不会发现有些PDF文件为了保密性会进行加密,如果我们经常需要使用它,就需要不断地输入密码,这…

Navicat使用教程

文章目录1.连接数据库1.1 启动MySQL1.2 Navicat连接数据库1.3 操作数据库1.4 导入EXcel表内容1.5 新建查询1.连接数据库 1.1 启动MySQL 使用管理员身份打开命令提示符 net start mysql 启动服务 net stop mysql 关闭服务 1.2 Navicat连接数据库 第一步:连接数据库之前一定要…

基于ZigBee设计的物联网LED控制系统

1. 前言 随着LED照明越来越普及以及移动互联网技术的快速发展,人们对家居生活的网络化、智能化、节能化的需求越来越强烈,将家用电器、照明灯具等模块通过无线网络集成到控制平台,实现智能控制和智能管理,目前智能LED照明已成为IOT中重要的一部分。 本文为了绿色智慧照明…

构建企业级DNS系统(十)搭建Docker容器bind

把bind运行在docker中 伴随着应用微服务化,大量应用跑在了容器之中,为了让容器的管理更可靠、可控并为上层应用提供更好的体验,更快的发布,更灵活的调度,容器云应运而生。 当各种上层应用跑在了容器之中,大…