美团一面:说一说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的博客,专注分享Java技术干货,包括Java基础、Spring Boot、Spring Cloud、Mysql、Redis、Elasticsearch、中间件、架构设计、面试题、程序员攻略等。

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

如若内容造成侵权/违法违规/事实不符,请联系长河编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

选择最佳图像处理工具OpenCV、JAI、ImageJ、Thumbnailator和Graphics2D

文章目录 1、前言2、 图像处理工具效果对比2.1 Graphics2D实现2.2 Thumbnailator实现2.3 ImageJ实现2.4 JAI&#xff08;Java Advanced Imaging&#xff09;实现2.5 OpenCV实现 3、图像处理工具结果 1、前言 SVD(stable video diffusion)开放了图生视频的API&#xff0c;但是限…

C#多态性

文章目录 C#多态性静态多态性函数重载函数重载 动态多态性运行结果 C#多态性 静态多态性 在编译时&#xff0c;函数和对象的连接机制被称为早期绑定&#xff0c;也被称为静态绑定。C# 提供了两种技术来实现静态多态性。分别为&#xff1a; 函数重载 运算符重载 运算符重载将…

基于React的低代码平台开发实践

&#x1f482; 个人网站:【 摸鱼游戏】【神级代码资源网站】【工具大全】&#x1f91f; 一站式轻松构建小程序、Web网站、移动应用&#xff1a;&#x1f449;在线地址&#x1f91f; 基于Web端打造的&#xff1a;&#x1f449;轻量化工具创作平台&#x1f485; 想寻找共同学习交…

2023混合多比特层-RDHEI Based on the Mixed Multi-Bit Layer Embedding Strategy

RRBE 本文仅供自我学习记录,切勿转载和搬运,如有侵权联系立删! 方法总框架 首先,发送者将载体图像进行两轮的不重叠块分割,分为可用隐藏块(AHB)和不可用隐藏块(UHB),然后通过依次处理可用块的像素信息产生location图来创造空间,接着通过密钥将载体进行加密,最后使用…

ElasticSearch启动报错:Exception in thread “main“ SettingsException

Exception in thread "main" SettingsException[Failed to load settings from [elasticsearch.yml]]; nested: ParsingException[Failed to parse object: expecting token of type [START_OBJECT] but found [VALUE_STRING]]; 这个报错说明elasticsearch.yml这个配…

如何在VS Code上搭建 C/C++开发环境

顾得泉&#xff1a;个人主页 个人专栏&#xff1a;《Linux操作系统》 《C从入门到精通》 《LeedCode刷题》 键盘敲烂&#xff0c;年薪百万&#xff01; 一、什么是VScode VScode&#xff08;Visual Studio Code&#xff09;是一款由微软开发的免费开源的轻量级代码编辑器。它…

机器视觉学习(七)—— 卷积、边缘和滤波器

目录 一、卷积运算 1.1 卷积运算的公式 1.2 卷积操作 二、垂直边缘与水平边缘 2.1 cv2.filter2D()函数 2.2 Sobel算子 三、滤波器 一、卷积运算 1.1 卷积运算的公式 卷积运算是一种图像处理的基本操作&#xff0c;常用于图像滤波、边缘检测等应用中。 卷积运算的基本思…

【Linux】 centos7安装卸载SQL server(2017、2019)

一、安装配置 准备一个基础Linux配置&#xff1a; 内存为20GB 运行内存为2GB的系统&#xff08;数据库小于2GB安装不了&#xff09; 1、网络配置 我们需要进行网络的连接 进入 cd /ect/sysconfig/network-script/ 编辑文件ifcfg-ens33 vi ifcfg-ens33 Insert键进行编辑 把ONBOO…

公平锁和非公平锁,为什么要“非公平”?

公平锁和非公平锁&#xff0c;为什么要“非公平”&#xff1f; 主要讲一讲公平锁和非公平锁&#xff0c;以及为什么要“非公平”&#xff1f; 什么是公平和非公平 首先&#xff0c;我们来看下什么是公平锁和非公平锁&#xff0c;公平锁指的是按照线程请求的顺序&#xff0c;…

后端常问面经之Java基础

基本数据类型 Java中有8种基本数据类型&#xff1a; 6种数字类型&#xff1a; 4种整数型&#xff1a;byte、short、int、long 2种浮点型&#xff1a;float、double 1种字符类型&#xff1a;char 1种布尔类型&#xff1a;boolean 数据类型的默认值以及所占空间如下&#x…

java智慧城管执法平台源码,现场移动执法APP源码

智慧城管执法平台源码 智慧城管综合执法办案系统&#xff0c;提供了案件在线办理、当事人信用管理、文书电子送达、沿街店铺分析等功能&#xff0c;全面赋能执法队员&#xff0c;提高执法队员办案效率。 智慧城管综合执法办案系统在业务上能够支持所有行政处罚权力项目的网上…

一文整合工厂模式、模板模式、策略模式

为什么使用设计模式 今天终于有时间系统的整理一下这几个设计模式了&#xff0c; 这几个真是最常用的&#xff0c;用好了它们&#xff0c;你就在也不用一大堆的if else 了。能更好的处理大量的代码冗余问题。 在我们的实际开发中&#xff0c;肯定会有这样的场景&#xff1a;我…

High 级别反射型 XSS 攻击演示(附链接)

环境准备 如何搭建 DVWA 靶场保姆级教程&#xff08;附链接&#xff09;https://eclecticism.blog.csdn.net/article/details/135834194?spm1001.2014.3001.5502 测试 打开靶场找到该漏洞页面 先右键检查输入框属性 还是和之前一样的&#xff0c;所以直接输入 HTML 标签提交…

Ruoyi若依框架下载流程详细解读(SpringBoot-Vue)

图解&#xff1a; 前端设计&#xff1a; 前端设计一个link文字连接或者按钮&#xff08;ElementUI&#xff09;Element - The worlds most popular Vue UI framework 前端请求设计&#xff1a; import request from /utils/request //下载示例模型定义语言的JSON export const…

文件编辑命令—vim

1.vim vim 是vi的升级版本.vi 文件名(vi方向键用不了) vim 的官方网站 (welcome home : vim online) 自己也说 vim 是一个程序开发工具而不是文字处理软件。 2.安装vim sudo apt install vim 如果出错了:apt update:刷新软件源; 出现"无法获得锁 之类的"sudo rm 文件…

【C语言基础】:内存操作函数

文章目录 一、memcpy函数的使用和模拟实现1.1 memcpy函数的使用1.2 memcpy函数的模拟实现 二、memmove函数的使用和模拟实现2.1 memmove函数的使用2.2 memmove函数的模拟实现 三、memset函数的使用3.1 menset函数的使用 四、memcmp函数的使用4.1 memcmp函数的使用 书山有路勤为…

K8S Storage

概述 一般情况下&#xff0c;K8S中的Pod都不应该将数据持久化到Pod中&#xff0c;因为Pod可能被随时创建和删除&#xff08;扩容或缩容&#xff09;&#xff0c;即便是StatefulSet或Operator的Pod&#xff0c;也都不建议在Pod里存放数据&#xff0c;可以将数据持久化到Host上。…

各种排序介绍

1.排序的概念 排序 &#xff1a;所谓排序&#xff0c;就是使一串记录&#xff0c;按照其中的某个或某些关键字的大小&#xff0c;递增或递减的排列起来的操作。 稳定性 &#xff1a;假定在待排序的记录序列中&#xff0c;存在多个具有相同的关键字的记录&#xff0c;若经过排…

Microsoft Excel 快捷键 (keyboard shortcut - hotkey)

Microsoft Excel 快捷键 [keyboard shortcut - hotkey] References 表格内部换行快捷键 Alt Enter 快速将光标移到表末 Ctrl End 快速将光标移到表首 Ctrl Home References [1] Yongqiang Cheng, https://yongqiang.blog.csdn.net/

学生宿舍智能控电柜安装调试技术

学生宿舍智能控电柜安装调试石家庄光大远通电器有限公司宿舍控电限电管理系统是一种用于管理学生宿舍用电的智能系统&#xff0c;主要功能包括: 1.实时监控和控制:该系统能够实时监测和记录宿舍的用电情况&#xff0c;包括电器使用情况、电量消耗等。管理人员可以通过电脑或手机…