说一说Java中的四种引用类型?

引言

在JDK1.2之前Java并没有提供软引用、弱引用和虚引用这些高级的引用类型。而是提供了一种基本的引用类型,称为Reference。并且当时Java中的对象只有两种状态:被引用和未被引用。当一个对象被引用时,它将一直存在于内存中,直到它不再被任何引用指向时,才会被垃圾回收器回收。而被引用也就是强引用。

而在JDK1.2之后对引用的概念进行了扩充,分为了强引用(StrongReference)、软引用(SoftReference)、弱引用(WeakReference)和虚引用(PhantomReference),这4种引用的强度依次减弱。他们的关系如下如:

image.png

强引用

强引用是Java中最常见的引用类型。当你创建一个对象并将其赋值给一个变量时,这个变量会持有该对象的强引用。

Order order = new Order(); // 只要order还指向Order对象,那么Order对象就不会被回收
order = null; // 强引用都被设置为 null 时,不可达,则Order对象被回收

只要存在强引用指向对象,垃圾回收器将永远不会回收该对象,即使内存不足也不会回收。这可能导致内存溢出,因为即使内存不足,JVM也不会回收强引用对象。当强引用都被设置为null时,对象变成不可达状态,垃圾回收器会在适当的时候将其回收。

比如以下示例,我们创建一个2M的数组,但是我们设置JVM参数:-Xms2M -Xmx3M,将JVM的初始内存设为2M,最大可用内存为3M。

public static void main(String[] args) {  
    //定义一个2M的数组  
    byte[] objects = new byte[1024 * 1024 * 2];  
}

此时我们执行方法后,发现报错:

image.png

对于强引用,即使内存不够使用,直接报错OOM,强引用也不会被回收。

对于强引用,就好比生活中,当我们拥有家里的钥匙时,我们可以随时进入你的家,即使我们不需要进入,也能确保我们可以进入。钥匙是我们进入家的强引用。只有当我们不再拥有钥匙时,我们才无法进入家,类似于当没有强引用指向一个对象时,该对象才能被垃圾回收。

软引用

在JDK1.2之后,用java.lang.ref.SoftReference类来表示软引用。软引用允许对象在内存不足时被垃圾回收器回收。如果一个对象只有软引用指向它,当系统内存不足时,垃圾回收器会尝试回收这些对象来释放内存,如果回收了软引用对象之后仍然没有足够的内存,才会抛出内存溢出异常。软引用适用于需要缓存大量对象,但又希望在内存不足时释放部分对象以避免内存溢出的情况,用于实现缓存时,当内存紧张时,可以释放部分缓存对象以保证系统的稳定性。

以下示例我们设置JVM参数为:-Xms3M -Xmx5M,然后连续创建了10个大小为1M的字节数组,并赋值给了软引用,然后循环遍历将这些对象打印出来。

private static final List<Object> list = Lists.newArrayList();  
  
public static void main(String[] args) {  
    IntStream.range(0, 10).forEach(i -> {  
        byte[] buff = new byte[1024 * 1024];  
        SoftReference<byte[]> sr = new SoftReference<>(buff);  
        list.add(sr);  
    });  
  
    System.gc(); // 主动通知垃圾回收  
  
    list.forEach(l -> {  
        Object obj = ((SoftReference<?>) l).get();  
        System.out.println("Object: " + obj);  
    });  
}

然后我们执行代码之后:

image.png

对于打印结果中,只有最后一个对象保留了下来,其他的obj全都被置空回收了。即说明了在内存不足的情况下,软引用将会被自动回收。

对于弱引用,就像我们医药箱里的备用药,当我们需要药品时,我们会先看看医药箱里是否有备用药。如果医药箱里有足够的药品(内存足够),我们就可以使用备用药;但如果医药箱里的备用药不够了(内存不足),我们可能会去药店购买。在内存不足时,垃圾回收器可能会回收软引用对象,类似于我们在医药箱里的备用药被用完时去药店购买。

弱引用

JDK1.2之后,用java.lang.ref.WeakReference来表示弱引用。弱引用与软引用类似,但强度更弱。即使内存足够,只要没有强引用指向一个对象,垃圾回收器就可以随时回收该对象。弱引用适用于需要临时引用对象的场景,如临时缓存或临时存储对象。也可以用于解决对象之间的循环引用问题,避免内存泄漏。

对于上述示例中,我们将数组赋值给弱引用

private static final List<Object> list = Lists.newArrayList();  
  
public static void main(String[] args) {  
    IntStream.range(0, 10).forEach(i -> {  
        byte[] buff = new byte[1024 * 1024];  
        WeakReference<byte[]> sr = new WeakReference<>(buff);  
        list.add(sr);  
    });  
  
    System.gc(); // 主动通知垃圾回收  
  
    list.forEach(l -> {  
        Object obj = ((WeakReference<?>) l).get();  
        System.out.println("Object: " + obj);  
    });  
}

执行结果发现所有的对象都是null,即都被回收了。

image.png

对于弱引用,就像我们正在旅行,使用一张一次性地图。我们只在需要导航时使用地图,一旦旅行结束,我们就不再需要地图了。这时我们可以选择扔掉地图,类似于弱引用,在垃圾回收器运行时,无论内存是否充足,对象都可能被回收。

虚引用

在 JDK1.2之后,用java.lang.ref.PhantomReference类来表示虚引用。虚引用是最弱的引用类型,它几乎对对象没有任何影响,不能通过虚引用获取对象,也不能通过它来阻止对象被垃圾回收。从源码中可以看出它只有一个构造函数和一个 get() 方法,而且它的 get() 方法仅仅是返回一个null,也就是说将永远无法通过虚引用来获取对象,虚引用必须要和 ReferenceQueue 引用队列一起使用。

image.png

虚引用可以用于在对象被回收时进行后续操作,如对象资源释放或日志记录,常用于跟踪对象被垃圾回收的状态,执行一些清理工作。

而对于弱引用,就像我们去商店,商店入口处的门闩并不直接影响你进入房屋,但它会在有人进入或离开时发出声音,提醒你有人进店(欢迎光临)或者离开(欢迎再来)。类似地,虚引用并不直接影响对象的生命周期,但它可以在对象被回收时发出通知,让你有机会进行一些后续操作,比如资源释放或者记录日志。

引用队列

引用队列(ReferenceQueue)是Java中的一个特殊队列,用于配合软引用、弱引用和虚引用,实现更灵活的对象引用和回收管理。

引用队列的主要作用是跟踪对象的垃圾回收过程。当一个软引用、弱引用或虚引用指向的对象被垃圾回收器回收时,如果它们与一个引用队列关联,那么这些引用就会被自动加入到引用队列中。通过监视引用队列中的对象,我们可以了解到对象的回收状态,从而执行一些额外的操作,比如资源释放或日志记录等。

总结

Java中的四种引用类型各具特点,可根据程序需求选择合适的引用类型。强引用保证对象不被意外回收,软引用和弱引用用于实现缓存或解决内存敏感问题,而虚引用则用于对象回收后的通知和清理操作。合理使用引用类型可以更好地管理内存和避免内存泄漏问题。

文章转载自:码农Academy

原文链接:https://www.cnblogs.com/coderacademy/p/18089036

体验地址:引迈 - JNPF快速开发平台_低代码开发平台_零代码开发平台_流程设计器_表单引擎_工作流引擎_软件架构

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

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

相关文章

NSCaching: Simple and Efficient NegativeSampling for Knowledge Graph Embedding

摘要 知识图嵌入是数据挖掘研究中的一个基本问题&#xff0c;在现实世界中有着广泛的应用。它的目的是将图中的实体和关系编码到低维向量空间中&#xff0c;以便后续算法使用。负抽样&#xff0c;即从训练数据中未观察到的负三元组中抽取负三元组&#xff0c;是KG嵌入的重要步…

优思学院|质量工程师的该有哪些技能与素养?

质量工程师作为制造业中的核心角色&#xff0c;致力于确保产品的整体质量。这不仅涉及到测试和监控过程&#xff0c;还包括创建文档、设计质量测试&#xff0c;并且定义测试结果应达到的标准&#xff0c;所以他既懂得生产技术&#xff0c;又精通管理知识。在本篇文章中&#xf…

springboot3使用​自定义注解+Jackson优雅实现接口数据脱敏

⛰️个人主页: 蒾酒 &#x1f525;系列专栏&#xff1a;《spring boot实战》 &#x1f30a;山高路远&#xff0c;行路漫漫&#xff0c;终有归途 目录 写在前面 内容简介 实现思路 实现步骤 1.自定义脱敏注解 2.编写脱敏策略枚举类 3.编写JSON序列化实现 4.编写测…

【Python小工具系列】使用 Python 循环批量打开网页链接

&#x1f49d;&#x1f49d;&#x1f49d;欢迎来到我的博客&#xff0c;很高兴能够在这里和您见面&#xff01;希望您在这里可以感受到一份轻松愉快的氛围&#xff0c;不仅可以获得有趣的内容和知识&#xff0c;也可以畅所欲言、分享您的想法和见解。 推荐:kwan 的首页,持续学…

工程项目管理系统专业解决方案!企智汇工程项目管理专业解决方案!

1.企智汇工程项目管理系统打造数智化全流程平台&#xff0c;打通全公司数据&#xff0c;实现公司业财一体化全方位管理。 企智汇工程项目管理系统&#xff0c;打通钉钉与企业微信的入口、可与财务系统做数据对接&#xff0c;统一共享数据源的企业一站式数智化项目管理平台&…

openGauss学习笔记-250 openGauss性能调优-使用Plan Hint进行调优-Join方式的Hint

文章目录 openGauss学习笔记-250 openGauss性能调优-使用Plan Hint进行调优-Join方式的Hint250.1 功能描述250.2 语法格式250.3 参数说明250.4 示例 openGauss学习笔记-250 openGauss性能调优-使用Plan Hint进行调优-Join方式的Hint 250.1 功能描述 指明Join使用的方法&#…

Affinity Publisher:你的出版利器,让创意绽放光彩!mac/win版

Affinity Publisher是一款功能强大的桌面出版软件&#xff0c;专为专业出版人员、设计师和印前专家设计。它提供了从构思到印刷的完整工作流程&#xff0c;让用户能够轻松创建高质量的出版物&#xff0c;包括杂志、书籍、小册子、海报等。 Affinity Publisher软件获取 Affinit…

C语言字节对齐关键字__attribute__((aligned(n)))的使用

0 前言 在进行嵌入式开发的过程中&#xff0c;我们经常会见到对齐操作。这些对齐操作有些是为了便于实现指针操作&#xff0c;有些是为了加速对内存的访问。因此&#xff0c;学习如何使用对齐关键字是对于嵌入式开发是很有必要的。 1 对齐规则 1.0 什么叫做对齐 众所周知&a…

Spring Bean 依赖注入(下)

不管是在属性上面还是在方法上面加了Autowired注解都是根据属性的类型和名字去找bean&#xff0c; set方法多个形参也是这么找 拿到所有的属性和方法的注入点后&#xff0c;会去调用Inject()方法 遍历每一个注入点然后进行注入 字段的注入 一开始肯定是没有缓存的&#xff0…

SpringBoot3+JPA+MySQL实现多数据源的读写分离(基于EntityManagerFactory)

1、简介 在Spring Boot中配置多个数据源并实现自动切换EntityManager&#xff0c;这里我编写了一个RoutingEntityManagerFactory和AOP&#xff08;面向切面编程&#xff09;的方式来实现。 这里我配置了两个数据源&#xff1a;primary和secondary&#xff0c;其中primary主数…

Redis - 高并发场景下的Redis最佳实践_翻过6座大山

文章目录 概述6座大山之_缓存雪崩 &#xff08;缓存全部失效&#xff09;缓存雪崩的两种常见场景如何应对缓存雪崩&#xff1f; 6座大山之_缓存穿透&#xff08;查询不存在的 key&#xff09;缓存穿透的原因解决方案1. 数据校验2. 缓存空值3. 频控4. 使用布隆过滤器 6座大山之_…

hash冲突四种解决办法,hash冲突除了拉链法还有什么?

1. 看hashmap 源码&#xff0c;有个问题&#xff0c;key 存放是 先hash 再与hash值的高16位值 进行异或运算。再与槽位size() 求模取余。如果多个不同的key 得出de数组位置相同。则采用链表依次存储。 2. 那么除了拉链法还有什么其他解决hash冲突的方法呢&#xff1f; a. 建立…

【学习】Web安全测试需要考虑哪些情形

一、数据加密 某些数据需要进行信息加密和过滤后才能在客户端和服务器之间进行传输&#xff0c;包括用户登录密码、信用卡信息等。例如&#xff0c;在登录某银行网站时&#xff0c;该网站必须支持SSL协议&#xff0c;通过浏览器访问该网站时&#xff0c;地址栏的http变成https…

堂哥让我给他做个真人动漫头像

背景 堂哥最喜欢的动漫是死神。他给了我一张死神主角一户的头像&#xff0c;以及自己的头像&#xff0c;希望我产出一张真人动漫头像。 一户的头像&#xff1a; 堂哥自拍照&#xff1a; 最近&#xff0c;有大佬部署了个stable diffusion&#xff0c;正好拿来一试身手。 stab…

vue项目报这个错是 Same `value` exist in the tree: 0008E3000E1A?

警告 "Same value exist in the tree: 0008E3000E1A" 表示在树形选择器中存在相同的值。这通常是由于树形选择器的数据中存在重复的值造成的。就是返回的值中&#xff0c;有俩个id相同

【Redis】数据类型、事务执行、内存淘汰策略

目录 数据类型 Redis事务执行步骤 步骤&#xff1a; redis内存淘汰策略 设置内存淘汰策略 1.设置配置文件 2.通过命令设置 数据类型 官网解释 Understand Redis data types | Redis 首先&#xff0c;Redis 的所有键都是字符串,常用的数据类型有 5 种&#xff1a;Strin…

快速上手 Elasticsearch:Docker Compose 部署详解

最近面试竞争日益激烈&#xff0c;Elasticsearch作为一款广泛应用的中间件&#xff0c;几乎成为面试中必考的知识点。最近&#xff0c;AIGC也备受关注&#xff0c;而好多的AI项目中也采用了Elasticsearch作为向量数据库&#xff0c;因此我们迫切希望学习Elasticsearch。对于学习…

【机器学习】基于变色龙算法优化的BP神经网络分类预测(SSA-BP)

目录 1.原理与思路2.设计与实现3.结果预测4.代码获取 1.原理与思路 【智能算法应用】智能算法优化BP神经网络思路【智能算法】变色龙优化算法&#xff08;CSA)原理及实现 2.设计与实现 数据集&#xff1a; 数据集样本总数2000 多输入多输出&#xff1a;样本特征24&#xff…

工业4.0 底层逻辑

许多场合下&#xff0c;工业4.0 的概念已经被滥用了&#xff0c;它与物联网&#xff0c;工业物联网等概念被滥用一样&#xff0c;几乎什么都往里面装。演变成了一句口号和愿景。许多人并不清楚工业4.0的底层逻辑到底是什么&#xff1f;如何遵循工业4.0 的思想构建新一代智能制造…

社交媒体行业巨头:揭示Facebook的市场地位

引言 随着数字化时代的蓬勃发展&#xff0c;社交媒体已经深刻改变了人们的生活方式和社会交往方式&#xff0c;而Facebook作为其中的领军者&#xff0c;扮演着举足轻重的角色。本文将深入探讨Facebook在社交媒体行业中的市场地位&#xff0c;从用户规模、收入来源、技术创新、…
最新文章