Java强软弱虚四种引用,看完不再犯迷糊
其实强引用、软引用、弱引用、虚引用这四个概念非常简单好记。
在开头先总结一下这四个引用的特点吧。
强引用:gc时不会回收
软引用:只有在内存不够用时,gc才会回收
弱引用:只要gc就会回收
虚引用:是否回收都找不到引用的对象,仅用于管理直接内存
接下来详细看看这四种引用,结合代码,深刻的体会一下。
强引用
即我们平时最常见的:
Object object = new Object();
只要一个对象有强引用,垃圾回收器就不会进行回收。即便内存不够了,抛出OutOfMemoryError异常也不会回收。
上demo,注意注释
/** * 一个对象 * 重写finalize方法,可以知道已经被回收的状态 * * @author * @date 2020-05-23 */ public class OneObject { @Override protected void finalize() throws Throwable { System.out.println("啊哦~OneObject被回收了"); } } /** * 强引用例子 * * @author * @date 2020-05-23 */ public class ShowStrongReference { public static void main(String[] args) { // 直接new一个对象,就是强引用 OneObject oneObject = new OneObject(); System.out.println("输出对象地址:" + oneObject); System.gc(); System.out.println("第一次gc后输出对象地址:" + oneObject); oneObject = null; System.gc(); System.out.println("置为null后gc输出对象地址:" + oneObject); } }
执行代码,可以看到以下输出:
输出对象地址:com.esparks.pandora.learning.references.OneObject@72ea2f77 第一次gc后输出对象地址:com.esparks.pandora.learning.references.OneObject@72ea2f77 置为null后gc输出对象地址:null 啊哦~OneObject被回收了
软引用
需要通过SoftReference对象实现:
SoftReference<OneObject> oneObjectSr = new SoftReference<>(new OneObject());
当内存足够的时候,垃圾回收器不会进行回收。当内存不够时,就会回收只存在软引用的对象释放内存。
常用于本地缓存处理。
上demo,注意注释
/** * 软引用 * 内存不够了就会回收 * 注意,运行时需要保证heap大小为35m,即小于实验中全部对象的大小,才能触发gc * -Xmx35m * * @author * @date 2020-05-23 */ public class ShowSoftReference { public static void main(String[] args) { // 我们需要通过SoftReference来创建软引用 SoftReference<OneObject> oneObjectSr = new SoftReference<>(new OneObject()); // 我们这里创建一个大小为20m的数组 SoftReference<byte[]> arraySr = new SoftReference<>(new byte[1024 * 1024 * 20]); System.out.println("软引用对象oneObjectSr的地址:" + oneObjectSr); System.out.println("通过oneObjectSr关联的oneObject对象的地址:" + oneObjectSr.get()); System.out.println("数组的地址:" + arraySr.get()); System.gc(); System.out.println("正常gc一次之后,oneObject对象并没有回收。地址" + oneObjectSr.get()); // 再创建另一个大小为20m的数组,这样heap就不够大了,从而系统自动gc。如果依旧不够,会把已有的软引用关联的对象都回收掉。 System.out.println("创建另一个大小为20m的数组otherArray"); byte[] otherArray = new byte[1024 * 1024 * 20]; System.out.println("otherArray的地址:" + otherArray); // gc后,软引用对象还在,但是通过软引用对象创建的对象就被回收了 System.out.println("现在srObject的地址:" + arraySr); System.out.println("现在srObject中oneObject对象的地址:" + arraySr.get()); System.out.println("刚才的数组对象也被回收啦,地址:" + arraySr.get()); } }
执行代码,可以看到以下输出:
软引用对象oneObjectSr的地址:java.lang.ref.SoftReference@72ea2f77 通过oneObjectSr关联的oneObject对象的地址:com.esparks.pandora.learning.references.OneObject@33c7353a 数组的地址:[B@681a9515 正常gc一次之后,oneObject对象并没有回收。地址com.esparks.pandora.learning.references.OneObject@33c7353a 创建另一个大小为20m的数组otherArray 啊哦~OneObject被回收了 otherArray的地址:[B@3af49f1c 现在srObject的地址:java.lang.ref.SoftReference@19469ea2 现在srObject中oneObject对象的地址:null 刚才的数组对象也被回收啦,地址:null
弱引用
需要通过WeakReference对象实现:
WeakReference<OneObject> oneObjectWr = new WeakReference<>(new OneObject());
只要发生gc,就会回收只存在弱引用的对象。
常用于Threadlocal。
上demo,注意注释
/** * 弱引用 * 只要gc就会回收 * * @author * @date 2020-05-23 */ public class ShowWeakReference { public static void main(String[] args) { // 我们需要通过WeakReference来创建弱引用 WeakReference<OneObject> objectWr = new WeakReference<>(new OneObject()); System.out.println("弱引用objectWr的地址:" + objectWr); System.out.println("弱引用objectWr关联的oneObject对象的地址:" + objectWr.get()); System.gc(); // gc后,弱引用对象还在,但是通过弱引用对象创建的对象就被回收了 System.out.println("gc后,弱引用objectWr的地址:" + objectWr); System.out.println("gc后,弱引用objectWr关联的oneObject对象的地址:" + objectWr.get()); } }
执行代码,可以看到以下输出:
弱引用objectWr的地址:java.lang.ref.WeakReference@72ea2f77 弱引用objectWr关联的oneObject对象的地址:com.esparks.pandora.learning.references.OneObject@33c7353a gc后,弱引用objectWr的地址:java.lang.ref.WeakReference@72ea2f77 gc后,弱引用objectWr关联的oneObject对象的地址:null 啊哦~OneObject被回收了
虚引用
需要通过PhantomReference对象和ReferenceQueue实现:
private ReferenceQueue<OneObject> queue = new ReferenceQueue<>(); PhantomReference<OneObject> oneObjectPr = new PhantomReference<>(new OneObject(), queue);
无论是否gc,其实都获取不到通过PhantomReference创建的对象。
其仅用于管理直接内存,起到通知的作用。
这里补充一下背景。因为垃圾回收器只能管理JVM内部的内存,无法直接管理系统内存的。对于一些存放在系统内存中的数据,JVM会创建一个引用指向这部分内存。
当这个引用在回收的时候,就需要通过虚引用来管理指向的系统内存。这里还需要依赖一个队列来实现。当触发gc对一个虚引用对象回收时,会将虚引用放入创建时指定的ReferenceQueue中。之后单独对这个队列进行轮训,并做额外处理。
上demo,注意注释
/** * 虚引用 * 只用于管理直接内存,起到通知的作用 * * @author * @date 2020-05-23 */ public class ShowPhantomReference { /** * 虚引用需要的队列 */ private static final ReferenceQueue<OneObject> QUEUE = new ReferenceQueue<>(); public static void main(String[] args) { // 我们需要通过WeakReference来创建虚引用 PhantomReference<OneObject> objectPr = new PhantomReference<>(new OneObject(), QUEUE); System.out.println("虚引用objectPr的地址:" + objectPr); System.out.println("虚引用objectPr关联的oneObject对象的地址:" + objectPr.get()); // 触发gc,然后检查队列中是否有虚引用 while (true) { System.gc(); Reference<? extends OneObject> poll = QUEUE.poll(); if (poll != null) { System.out.println("队列里找到objectPr啦" + poll); break; } } } }
执行代码,可以看到以下输出:
虚引用objectPr的地址:java.lang.ref.PhantomReference@73ea3f33 虚引用objectPr关联的oneObject对象的地址:null 啊哦~OneObject被回收了 队列里找到objectPr啦java.lang.ref.PhantomReference@73ea2f33
原文链接: https://www.yukx.com/architect/article/details/2362.html 优科学习网Java强软弱虚四种引用,看完不再犯迷糊
-
如何看到老年代、新生代的对象有哪些呢?MAT是分析dump的神器(顺便吐槽:当然也是吃内存卡机器的怪兽)。通常我们会在出现fullGC时dump下堆内存,然后分析FullGC的原因。那如何获知整个堆内存里,有哪些对象在新生代、哪些在老年代呢?一个典型的应用场景是:出现了耗时超预期的YoungGC,我
-
面向服务的架构(SOA)是一种软件开发方法,它使用称为服务的软件组件来创建业务应用程序。每项服务提供一种业务能力,并且服务也可以跨平台和语言相互通信。开发人员使用SOA来重用不同系统中的服务,或者组合几个独立的服务来执行复杂的任务。例如,一个组织中的多个业务流程需要用户身份验证功能。您可以创建一项身
-
1.背景1.1什么是交互式推荐?交互式推荐是一种互动式实时推荐产品模块,主要通过理解用户需求、以互动的方式进行推荐。交互式推荐由Youtube在2018年提出,主要用于解决推荐系统的延迟和与用户互动偏弱的问题。从2021年下半年开始,美团外卖推荐技术团队在外卖首页Feed上持续进行探索,2022上半
-
导读:老是出现堆内存不足,大量FullGC深知出现内存溢出应该怎么办,怎样通过排查找到源头分析来解决问题?正文:我们有个新服务上线运行一段时间后,老是出现堆内存不足,大量出现FullGC,有些实例甚至出现内存溢出错误:java.lang.OutOfMemoryError:Javaheapspace但
-
其实强引用、软引用、弱引用、虚引用这四个概念非常简单好记。在开头先总结一下这四个引用的特点吧。强引用:gc时不会回收软引用:只有在内存不够用时,gc才会回收弱引用:只要gc就会回收虚引用:是否回收都找不到引用的对象,仅用于管理直接内存接下来详细看看这四种引用,结合代码,深刻的体会一下。强引用即我们平
-
在Linux中,CPU主要用于中断、内核以及用户进程的任务处理,优先级为中断内核用户进程,在学习如何分析CPU消耗状况前。先要掌握三个重要的概念1、上下文切换每个CPU在同一时间只能执行一个线程,Linux采用的是抢占式调度,即为每个线程分配一定的执行时间,当到达执行时间、线程中有IO阻塞或高级优先