您现在的位置是:首页 > 文章详情

Java 四种引用类型,强引用、软引用、弱引用、虚引用

日期:2020-08-03点击:449

云栖号资讯:【点击查看更多行业资讯
在这里您可以找到不同行业的第一手的上云资讯,还在等什么,快来!


前言

每种编程语言都有自己操作内存中元素的方式,例如在 C 和 C++ 里是通过指针,对于指针的使用,大家肯定记得刚学习时候的痛苦。

作为 OOP 面向对象编程的翘楚,在 Java 中一切都被视为了对象。但其实操作时候的标识符并不是真正的对象,而是对象的一个引用(reference)。

通过将这个叫“引用”的标识符指向某个对象,之后便可以使用这个引用来实现操作对象了。

在 JDK1.2 之前,Java中的定义很传统:如果 reference 类型的数据中存储的数值代表的是另外一块内存的起始地址,就称为这块内存代表着一个引用。

Java 中的垃圾回收机制在判断是否回收某个对象的时候,都需要依据“引用”这个概念。不同垃圾回收算法中,对引用的判断方式有所不同,典型的有引用计数法和可达性分析法。

JDK1.2 之前,一个对象只有“已被引用”和"未被引用"两种状态,这将无法描述某些特殊情况下的对象,比如,当内存充足时需要保留,而内存紧张时才需要被抛弃的一类对象。

所以在 JDK.1.2 之后,Java 对引用的概念进行了扩充,将引用分为了:强引用(Strong Reference)、软引用(Soft Reference)、弱引用(Weak Reference)、虚引用(Phantom Reference)4 种,这 4 种引用的强度依次减弱。

本篇文章将对这四种引用类型进行详细介绍。

正文

强引用

在 Java 中,我们默认声明的时候,使用的是强引用,比如:

A a = new A();

只要使用了强引用,垃圾回收器将永远不会回收被引用的对象。由于内存大小是一定的,当内存不足时,JVM 会直接抛出 OutOfMemoryError,因为没办法回收去释放空间。

如果想中断强引用与对象之间的关系,可以显示将其赋值为 null,这样一来JVM 就可以在适当的时候进行垃圾回收了。

A a = null;

软引用

软引用比强引用的程度减弱一些,表示是一些非必需但仍有用的对象。它的表现形式如下:

(1)内存足够的时候,软引用对象不会被回收。

(2)内存不足时,系统则会回收软引用对象。

如果软引用对象被回收之后,仍然没有足够的内存空间,然后会抛出内存溢出异常。

由于软引用的这种特性,非常适合实现缓存技术,比如网页缓存,图片缓存等等。

在 JDK1.2 之后,用java.lang.ref.SoftReference类来表示软引用。

弱引用

弱引用的强度还要更弱一些,它最主要的特点是:无论内存是否足够,只要 JVM 开始进行垃圾回收,那些被弱引用关联的对象都会被回收。

在 JDK1.2 之后,用 java.lang.ref.WeakReference 来表示弱引用。

我们可以用下面的小demo来测试一下:

private static void testWeakReference() { for (int i = 0; i < 10; i++) { byte[] buff = new byte[1024 * 1024]; WeakReference<byte[]> sr = new WeakReference<>(buff); list.add(sr); } System.gc(); //主动通知垃圾回收 for(int i=0; i < list.size(); i++){ Object obj = ((WeakReference) list.get(i)).get(); System.out.println(obj); } }

运行后会发现所有被弱引用关联的对象都被垃圾回收了。

在学习弱引用的时候,一个经典的例子就是 ThreadLocal,通过源代码我们发现它的内部数据结构就是由弱引用来实现的。

 static class ThreadLocalMap { /** * The entries in this hash map extend WeakReference, using * its main ref field as the key (which is always a * ThreadLocal object). Note that null keys (i.e. entry.get() * == null) mean that the key is no longer referenced, so the * entry can be expunged from table. Such entries are referred to * as "stale entries" in the code that follows. */ static class Entry extends WeakReference<ThreadLocal<?>> { /** The value associated with this ThreadLocal. */ Object value; Entry(ThreadLocal<?> k, Object v) { super(k); value = v; } } }

在使用 ThreadLocal 时如果忘记了remove操作,很容易出现内存泄露的问题,后续有时间我会专门写一篇文章再讲讲这个。

虚引用

虚引用是最弱的一种引用关系,如果一个对象仅持有虚引用,那么它就和没有任何引用一样,它随时可能会被回收。

在 JDK1.2 之后,用 PhantomReference 类来表示,通过查看这个类的源码,发现它只有一个构造函数和一个 get() 方法,而且它的 get() 方法仅仅是返回一个 null,也就是说将永远无法通过虚引用来获取对象,虚引用必须要和 ReferenceQueue 引用队列一起使用。

public class PhantomReference<T> extends Reference<T> { /** * Returns this reference object's referent. Because the referent of a * phantom reference is always inaccessible, this method always returns * <code>null</code>. * * @return <code>null</code> */ public T get() { return null; } public PhantomReference(T referent, ReferenceQueue<? super T> q) { super(referent, q); } }

总结

通过这篇文章介绍了 Java 语言中的四种引用类型,看完后我们发现这主要与Java 的垃圾回收机制和内存管理息息相关。JVM 作为基础,还是希望大家能够扎实的掌握。

【云栖号在线课堂】每天都有产品技术专家分享!
课程地址:https://yqh.aliyun.com/live

立即加入社群,与专家面对面,及时了解课程最新动态!
【云栖号在线课堂 社群】https://c.tb.cn/F3.Z8gvnK

原文发布时间:2020-08-03
本文作者:程序员大帝
本文来自:“掘金”,了解相关信息可以关注“掘金”

原文链接:https://yq.aliyun.com/articles/769544
关注公众号

低调大师中文资讯倾力打造互联网数据资讯、行业资源、电子商务、移动互联网、网络营销平台。

持续更新报道IT业界、互联网、市场资讯、驱动更新,是最及时权威的产业资讯及硬件资讯报道平台。

转载内容版权归作者及来源网站所有,本站原创内容转载请注明来源。

文章评论

共有0条评论来说两句吧...

文章二维码

扫描即可查看该文章

点击排行

推荐阅读

最新文章