Java中的Reference

news2024/11/15 4:34:13

1. 常用四种引用

快速记忆法:“硬(俗称的强引用) --> 软(SoftReference) --> 弱(WeakReference) --> 虚(PhantomReference)”
此处将常说的“强引用”记忆成“硬引用”可以对应到次席的“软引用”(反义词:硬-软)这样更容易记住

a. 强引用

平常我们代码中写到的引用类型都是强引用类型,比如Object obj = new Object();, Object实例就有一个强引用类型指向它,在GC过程中即使发生OOM,该Object实例都不会被回收。

b. 软引用 - SoftReference

定义方式:SoftReference sr = new SoftReference(new Object()); 一个对象的实例被一个软引用实例指向,那么在GC过程中发生OOM之前,该Object对象实例会被回收掉,在内存充足的情况下是不会被回收的。同时可以将一个引用队列关联到该软引用上,在软引用指向的对象被回收后,该软引用会被加入到关联的引用队列中。我们可以通过Reference的get()方法获取到该软引用指向的对象实例。

c. 弱引用 - WeakReference

弱引用基本上同上面的软引用类似,WeakReference wr = new WeakReference(new Object());,但是特殊点就是在它被创建后的下一次GC时候其指向的对象实例会被回收掉,不管内存是不是充足,反正就是活不过一次GC。JDK中的WeakHashMap就是使用到WeakReference,其Key就是被包装成WeakReference。

d. 虚引用 - PhantomReference

定义方式:PhantomReference pr = new PhantomReference(new Object(), new ReferenceQueue()),虚引用对象再被定义时,必须指定一个引用队列实例。JDK文档中介绍它主要用于对象被回收前资源的释放操作,替换finalize()方法。它和前面的两个软引用和弱引用不同的地方有两点:

2. 验证

虚引用在对象被回收之前添加到引用队列中,同时需要手动处理,它指向的对象才会被回收

思路:

a. 创建一个虚引用对象,然后发起一次GC操作,查看其指向的对象实例是否被回收

b. 通过检测它关联的引用队列,取出加入的虚引用对象,查看此时其指向的对象实例是否被回收

c. 调用虚引用对象的clear方法之后,查看其指向的对象实例是否被回收

2.1. 代码

public class ReferenceApp1 {
    public static void main(String[] args) throws Exception {
        phantom();
    }

    /**
     * 验证PhantomReference
     * @throws Exception
     */
    private static void phantom() throws Exception {
        // 步骤1. 定义一个InnerPhantomRefObj对象实例
        InnerPhantomRefObj innerPhantomRefObj = new InnerPhantomRefObj();
        innerPhantomRefObj.setName("InnerPhantomRefObj-1");
        ReferenceQueue<Object> referenceQueue = new ReferenceQueue<>();
        // 步骤2. 定义一个虚引用对象
        PhantomReference<Object> phtRef = new PhantomReference<>(innerPhantomRefObj, referenceQueue);

        // 移除InnerPhantomRefObj对象实例上的强引用,不然后面操作不会被回收
        innerPhantomRefObj = null;
        System.err.println("before gc | get PhantomReference referent:" + phtRef.get());
        // 步骤3. 发起GC操作
        System.gc();

        int i = 0;
        Reference tmp = null;
        while(true) {
            System.out.println("phantom iteration >>>> " + ++i);
            Thread.sleep(5000);
            if(i == 1) {
                // 步骤4. 从引用队列中取出虚引用对象
                tmp = referenceQueue.poll();
                if(tmp != null) {
                    System.err.println("get PhantomReference from ReferenceQueue");
                }
                // 发起一次GC操作,其实此时InnerPhantomRefObj对象不会被回收
                System.gc();
            }
            if(i == 5) {
                if(tmp != null) {
                    System.err.println("after gc | get PhantomReference referent:" + tmp.get());
                    // 步骤5. 调用虚引用上的clear方法,让下一次GC操作回收掉InnerPhantomRefObj对象
                    tmp.clear();

                    // 或者让GC操作释放PhantomReference对象实例
//                    tmp = null;
//                    phtRef = null;
                    System.err.println("clear PhantomReference");
                    // 发起一次GC操作
                    System.gc();
                }
            }
            if(i == 10) {
                break;
            }
        }
    }

    @Data
    private static class InnerPhantomRefObj {
        private String name;
    }
}

2.2. 观察VisualVM中实例个数变化判断是否被回收

a. 从上述代码的步骤1到步骤5之间的实例统计截图如:(实例个数为1,没有被回收)

b. 执行步骤5(调用PhantomReference的clear方法)之后的实例统计截图如:(实例个数为0,已被被回收)

在Java 8以及之前的版本中,在虚引用回收后,虚引用指向的对象才会回收。在Java 9以及更新的版本中,虚引用不会对对象的生存产生任何影响。

3. 类比

看到一篇英文博客中用一个例子来类比软、弱、虚引用三者之间的差别非常好,在此借用一下:

比如一个快餐店中,桌子座位有限,服务员会随时清理桌子座位,你进去点单,找到一个座位坐下,会存在下面几种情况

a. 然后后面有很多人过来点单时,当座位不够时你会让出座位,但在此之前每次服务员过来清理座位时你都没有让出座位,这种情况就像就像软引用

b. 第一次服务员过来清理桌子座位时,你就让出座位,这种情况就像弱引用

c. 第一次服务员过来清理桌子座位时,你可以随时准备让出座位,其实这时候你并没有让出位置,但是后面服务员说出一句让你让出座位时你才会让出座位,这种情况就像虚引用

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

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

相关文章

ExpressLRS开源代码之框架结构

ExpressLRS开源代码之框架结构 1. 源由2. Arduino应用框架3. ExpressLRS应用框架4. 硬件设计框架4.1 单天线4.2 双天线单PA4.3 双天线双PA 5. 应用软件设计6. 参考资料 1. 源由 最近为了理解《ExpressLRS开源之基本调试数据含义》&#xff0c;做了一些源代码的研读。 概念、文…

Nginx基础+高级(2022版):待更新

1. 文章说明 说明&#xff1a;目前讲的是第一部分nginx核心技术篇&#xff0c;后需篇章会以第一部分为核心技术篇为基础来展开深度讲解&#xff0c;详情关注后续课程的发布。 2. 介绍和准备环境 2.1 介绍 Nginx (engine x) 是一个高性能的HTTP和反向代理web服务器&#xf…

WebDAV之π-Disk派盘 + 人升

人升是一款融入了游戏化元素的待办事项应用,旨在为用户提供一种记录待办事项的过程像玩游戏打怪升级的体验。该应用致力于在保持实用性的基础上,扩展应用的乐趣。 在实用性方面,人升提供了以下功能: – 简洁界面:符合Material Design的简约界面,使新建待办事项变得更加轻…

嘉泰实业和您共创未来财富生活

每一次暖心的沟通都是一次公益,真诚不会因为它的渺小而被忽略;每一声问候都是一次公益,善意不会因为它的普通而被埋没。熟悉嘉泰实业的人都知道,这家企业不但擅长在金融理财领域里面呼风唤雨,同时也非常擅长在公益事业当中践行,属于企业的责任心,为更多有困难的群体带来大爱的传…

【机器视觉】HALCON目标图像检测实践(零基础版非常有用!)

开发环境&#xff1a; 基本思路&#xff1a; 灰度阈值处理特征提取 ps:思考&#xff1a;如何通过阈值处理后&#xff0c;后续缩小检测目标范围&#xff1f; 二值化、梯度阈值、自适应阈值等方法来增强图像的对比度&#xff0c;从而突出目标特征&#xff0c;进一步缩小检测目标…

对话永洪科技CEO何春涛:专注BI,决胜AI时代丨数据猿专访

大数据产业创新服务媒体 ——聚焦数据 改变商业 大数据、云计算、人工智能为代表的新一代信息技术走向普及&#xff0c;数据驱动业务&#xff0c;逐渐成为现代化企业管理、运作的日常。对于年均复合增长率超过20%的国内商业智能&#xff08;BI&#xff09;市场而言&#xff0c…

OpenHarmony 应用 ArkUI 状态管理开发范例

本文转载自《#2023 盲盒码 # OpenHarmony 应用 ArkUI 状态管理开发范例》&#xff0c;作者&#xff1a;zhushangyuan_ 本文根据橘子购物应用&#xff0c;实现 ArkUI 中的状态管理。 在声明式 UI 编程框架中&#xff0c;UI 是程序状态的运行结果&#xff0c;用户构建了一个 UI …

技术奇瑞高能出击,四大品牌联袂燃擎成都车展

8月25日&#xff0c;成都国际汽车展览会于中国西部国际博览城正式拉开帷幕。成都车展作为西南地区首屈一指的国内四大A级车展之一&#xff0c;不仅是下半年国内车市的风向标&#xff0c;也因天府之国弥漫着火锅味与茶香的烟火气而独具一番风味。成都车展上&#xff0c;奇瑞集团…

【校招VIP】前端算法考点之大数据相关

考点介绍&#xff1a; 大数据的关键技术分为分析技术和处理技术&#xff0c;可用于大数据分析的关键技术主要包括A/B测试&#xff0c;关联规则挖掘&#xff0c;数据挖掘&#xff0c;集成学习&#xff0c;遗传算法&#xff0c;机器学习&#xff0c;自然语言处理&#xff0c;模式…

17.看楼房

Description 小张在暑假时间进行了暑期社会调查。调查的内容是楼房的颜色如何影响人们的心情。于是他找到了一个楼房从左到右排成一排的小区&#xff0c;这个小区一共有 栋楼房&#xff0c;每个楼房有一个颜色 和一个高度 。小张调查的内容为每次他站在第 栋楼和第 栋楼之间向…

2240. 买钢笔和铅笔的方案数

文章目录 Tag题目来源题目解读解题思路复杂度分析写在最后 Tag 【枚举】【数学】 题目来源 2240. 买钢笔和铅笔的方案数 题目解读 现在你有一笔钱 total&#xff0c;用来购买钢笔和铅笔&#xff0c;它们的价格分别为 cost1 和 cost2&#xff0c;试问你可以有多少种不同的购…

CASAIM与北京协和医院达成合作,通过CT重建和3D打印技术为医学实验提供技术辅助和研究样本

近期&#xff0c;CASAIM与北京协和医院达成合作&#xff0c;通过CT重建和3D打印技术为医学实验提供技术辅助和研究样本&#xff0c;在实验样本的一致性和实验研究的严谨性原则下设计方案&#xff0c;推动产学研一体化发展。 北京协和医院是集医疗、教学、科研于一体的现代化综合…

【Tkinter系列04/15】界面小部件(选择钮、行编辑器)

九. 小部件Checkbutton 复选框小部件&#xff08;有时称为 “复选框”&#xff09;是允许用户阅读和 选择双向选项。上图显示了如何 复选按钮在关闭 &#xff08;0&#xff09; 和打开 &#xff08;1&#xff09; 状态下查看 实现&#xff1a;这是两个复选按钮的屏幕截图 使用 …

C#基础详解

Excerpt C#是微软公司发布的一种面向对象的、运行于 .NET Framework和 .NET Core&#xff08;完全开源&#xff0c;跨平台&#xff09;之上的高级程序设计语言。- C#是一种安全的、稳定的、简单的、优雅的&#xff0c;由C和C衍生出来的面向对象的编程语言。它在继承C和C强大功能…

threejs加载file格式的gltf模型,使用input type=file加载gltf模型

项目场景&#xff1a; 使用input选择gltf加载模型 问题描述 gltf有多个文件如何塞给GLTFLoader加载&#xff08;不知道怎么办&#xff09;。 解决方案&#xff1a; 最后在threejs官网看到解决办法 解决思路 URL.createObjectURL(bolb/file) 1&#xff1a;input输入文件获…

HummerRisk V1.4.0发布

大家好&#xff0c;HummerRisk 1.4.0和大家见面了&#xff0c;在这个版本中我们变更了多云检测的底层逻辑&#xff0c;增加了每次检测的project概念&#xff0c;更好的去支持检测历史和检索需要&#xff0c;增加阿里云最佳实践中资源监控检测规则&#xff0c;增加资源态势中的细…

TypeScript_队列结构-链表

队列 队列&#xff08;Queue&#xff09;&#xff0c;它是一种受限的线性表&#xff0c;先进先出&#xff08;FIFO First In First Out&#xff09; 受限之处在于它只允许在队列的前端&#xff08;front&#xff09;进行删除操作而在队列的后端&#xff08;rear&#xff09;进…

python后端,一个账户,多设备登录管理

一个账号&#xff0c;多台设备同时登陆的问题&#xff0c;设计以及实现 参考这篇文章&#xff1a; https://www.alibabacloud.com/help/zh/tair/use-cases/manage-multi-device-logon-from-a-single-user-by-using-tairhash1.0 设计思路 利用的是Redis&#xff0c;主设备的保…

Webgoat-Hijack a session通关答题教程

Webgoat-Hijack a session Hijack session是会话劫持&#xff0c;先了解需要用到的知识&#xff1a; Cookie原理&#xff1a; 1.客户端向服务端发起请求 2.服务端返回cookie&#xff0c;自己也保存了一份 3.客户端收到后&#xff0c;将cookie也保存起来 4.客户端再次发起请求时…

某物联网数智化园区行业基于 KubeSphere 的云原生实践

公司简介 作为物联网 数智化园区一体化解决方案提供商&#xff0c;我们致力于为大中型园区、停车场提供软硬件平台&#xff0c;帮助园区运营者实现数字化、智能化运营。 在使用 K8s 之前我们使用传统的方式部署上线&#xff0c;使用 spug&#xff08;一款轻量级无 Agent 的自…