Java中的Reference

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

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

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

Flink 如何定位反压节点?

分析&回答 Flink Web UI 自带的反压监控 —— 直接方式 Flink Web UI 的反压监控提供了 Subtask 级别的反压监控。监控的原理是通过Thread.getStackTrace() 采集在 TaskManager 上正在运行的所有线程&#xff0c;收集在缓冲区请求中阻塞的线程数&#xff08;意味着下游阻…

Dockerfile 使用教程

1.Dockerfile 1.1 什么是Dockerfile Dockerfile可以认为是 Docker镜像的描述文件&#xff0c;是由一系列命令和参数构成的脚本 。主要作用是 用来构建docker镜像的构建文件 。 通过架构图可以看出通过DockerFile可以直接构建镜像 1.2 Dockerfile解析过程 构建镜像步骤&#xf…

2023年高教社杯数学建模思路 - 案例:感知机原理剖析及实现

文章目录 1 感知机的直观理解2 感知机的数学角度3 代码实现 4 建模资料 # 0 赛题思路 &#xff08;赛题出来以后第一时间在CSDN分享&#xff09; https://blog.csdn.net/dc_sinor?typeblog 1 感知机的直观理解 感知机应该属于机器学习算法中最简单的一种算法&#xff0c;其…

LLM - LLaMA-2 获取文本向量并计算 Cos 相似度

目录 一.引言 二.获取文本向量 1.hidden_states 与 last_hidden_states ◆ hidden_states ◆ last_hidden_states 2.LLaMA-2 获取 hidden_states ◆ model config ◆ get Embedding 三.获取向量 Cos 相似度 1.向量选择 2.Cos 相似度 3.BERT-whitening 特征白化 …

.ssh文件夹下缺失known_hosts文件

.ssh文件夹下缺失known_hosts文件 先确认工蜂或github 添加了git生成的密钥 然后 桌面打开git bash 1、执行ssh -T gitgitlab.com 2、输入yes

b站手机缓存文件转MP4

b站缓存的文件 音频、视频、弹幕是分开的 这里我只用到了音频和视频所以只介绍这一部分 b站的缓存视频文件和路径结构如下 默认缓存路径 内部存储\Android\data\tv.danmaku.bilil\download\89720189 文件夹结构 文件夹 c_738583 这是单个视频的缓存文件夹 进入c_738583文件夹…

电脑可以上网,微信都可以用,但浏览器打不开网页

可以试试设置DNS&#xff08;其他windows版本步骤&#xff09;&#xff1a; 1.打开控制面板 2.网络和Internet 3.查看网络计算机和设备 4.按照下图步骤&#xff1a; 5.按下图进行

Unity 之 方括号[ ] 的用法以及作用

文章目录 在Unity中&#xff0c;方括号 [ ] 通常用于表示属性、特性&#xff08;Attributes&#xff09;或者元数据&#xff08;Metadata&#xff09;。这些标记提供了附加信息&#xff0c;可以用于修改类、方法、字段等的行为或者在编辑器中进行设置。 以下是一些常见的用法&…

基于stm32的烟雾浓度检测报警proteus仿真设计(仿真+程序+讲解)

基于STM32的烟雾浓度检测报警仿真设计(仿真程序讲解&#xff09; 1.主要功能2.仿真3. 程序4. 资料清单&下载链接 基于STM32的烟雾浓度检测报警仿真设计(仿真程序讲解&#xff09; 仿真图proteus 8.9 程序编译器&#xff1a;keil 5 编程语言&#xff1a;C语言 设计编号&a…

Huggingface托管机器学习模型及API提供

推荐&#xff1a;用 NSDT编辑器 快速搭建可编程3D场景 我想在我的网络和移动应用程序中使用机器学习模型&#xff0c;但要做到这一点&#xff0c;我必须在某个地方托管我的机器学习应用程序。 托管预先训练的 ML 模型称为推理。 我只想添加一些 Python ML 代码并快速获得 REST…

C语言:字符函数和字符串函数(一篇拿捏字符串函数!)

目录 求字符串长度&#xff1a; 1. strlen(字符串长度) 长度不受限制函数&#xff1a; 2. strcpy(字符串拷贝) 3. strcat(字符串追加) 4. strcmp(字符串比较) 长度受限制函数&#xff1a; 5. strncpy(字符串拷贝) 6. strncat(字符串追加) 7. strncmp(字符串比较) 字…

MR混合现实汽车维修情景实训教学演示

MR混合现实技术应用于汽车维修课堂中&#xff0c;能够赋予学生更加真实&#xff0c;逼真地学习环境&#xff0c;让学生在情景体验中不断提高自己的专业能力。 MR混合现实汽车维修情景实训教学演示具体体现在&#xff1a; 1. 虚拟维修指导&#xff1a;利用MR技术&#xff0c;可…

upgrade pip报错:def read(rel_path: str) -> str: syntaxerror

命令行执行以下命令就可以大功告成! wget https://bootstrap.pypa.io/pip/2.7/get-pip.py python get-pip.py pip install --upgrade setuptools最后大功告成:

Vue3+ts封装一个简单版的Message组件

Vue3ts封装一个Message组件 项目中需要使用信息提示框的功能&#xff0c;ui组件库使用的是字节的arco-design-vue。看了一下&#xff0c;现有的Message不满足要是需求&#xff0c;直接使用message组件的话&#xff0c;改样式太麻烦。Notification组件样式倒是符合了&#xff0c…

使用maven创建springboot项目

创建maven快速启动项目 命令行或者idea、eclipse快捷创建也可以 pom.xml下project项目下导入springboot 父工程 <!--导入springboot 父工程--> <parent><artifactId>spring-boot-starter-parent</artifactId><groupId>org.springframework.bo…

Flink+Paimon多流拼接性能优化实战

目录 &#xff08;零&#xff09;本文简介 &#xff08;一&#xff09;背景 &#xff08;二&#xff09;探索梳理过程 &#xff08;三&#xff09;源码改造 &#xff08;四&#xff09;修改效果 1、JOB状态 2、Level5的dataFile总大小 3、数据延迟 &#xff08;五&…

研华I/O板卡 Win10+Qt+Cmake 开发环境搭建

文章目录 一.研华I/O板卡 Win10QtCmake 开发环境搭建 一.研华I/O板卡 Win10QtCmake 开发环境搭建 参考这个链接安装研华I/O板卡驱动程序系统环境变量添加研华板卡dll Qt新建一个c项目 cmakeList.txt中添加研华库文件 cmake_minimum_required(VERSION 3.5)project(advantechDA…

科技资讯|苹果发布新专利:可在车内定位苹果的智能设备

根据美国商标和专利局近期公示的清单&#xff0c;苹果公司获得了一项名为《车内定位移动设备的系统和方式》专利&#xff0c;概述了在车内狭窄空间内如何定位 iPhone 等移动设备。 Find My 服务现阶段没有使用 UWB 来追踪 iPhone 或者 iPad&#xff0c;而是依赖 GPS 等相关辅…

【Java并发】聊聊对象内存布局和syn锁升级过程

对象存储解析&#xff1a;一个空Object对象到底占据多少内存&#xff1f; 对象内存布局 Mark Word占用8字节&#xff0c;类型指针占用8个字节&#xff0c;对象头占用16个字节。 好了&#xff0c;我们来看一下一个Object对占用多少空间&#xff0c; 因为java默认是开启压缩…