概述
今天记录下面试中常常问到的知识点:什么是强引用、弱引用、软引用、虚引用?
目录
- 1.什么是引用?
- 2.强引用
- 3.软引用
- 4.弱引用
- 5.虚引用
- 6.引用队列
- 7.参考资料
1.什么是引用?
首先,我们先来弄清什么是引用。
JAVA 中的一切皆对象,但除了基本类型是直接操作的原始值,其他都是通过引用(Reference)指向的存储了对象基本信息的内存地址。这也解释了我们在打印不同类型的对象时,为什么有的是原始值,有的是内存地址。
public static void main(String[] args) {
//指向内存中的值
String str = "abc";
System.out.println(str);
//指向内存中的地址
Object o = new Object();
System.out.println(o);
}
abc
java.lang.Object@1b6d3586
一个对象只有被引用和没被引用两种状态,没被引用的对象随时可能会被垃圾回收器进行回收,从而释放内存。
但我们希望某些对象在内存足够时,一直存储在内存之中;内存不够时,可以自动释放;为了让我们自己来控制对象的生命周期,JAVA 提供了四种引用类型,它们的引用强度依次由强至弱,分别为:
- 强引用
- 弱引用
- 软引用
- 虚引用
接下来和大家一起学习它们具体的使用场景。
2.强引用
强引用为 JAVA 中最常见的引用,即将一个对象赋值给一个引用对象 ,如:Object o = new Object()
。
当一个对象被引用变量引用时,即使发生内存不足,垃圾回收器也不会回收被强引用指向的对象,故这也是引发内存泄露的主要原因。
如同下例,不断往 LinkedList放入 Integer[] 数组,内存一直得不到释放,最终造成内存泄露。
public static void main(String[] args) {
LinkedList<Integer[]> linkedList = new LinkedList<>();
while (true){
linkedList.add(new Integer[1024*1024]);
}
}
Exception in thread "main" java.lang.OutOfMemoryError: Java heap space
at mtn.baymax.charpter17.ReferenceTest.main(ReferenceTest.java:15)
3.软引用
软引用需要通过 java.lang.ref.SoftReference来实现,不仅需要指定参数的泛型,还要往构造方法中放入实例对象;SoftReference 可通过 get() 返回存储的对象。
软引用中存储的对象,只有当内存不足时,才会被垃圾回收器清理。
如下述案例:当内存发生泄露时,垃圾回收器进行清理,同时会结束软引用存储对象的生命周期。
public static void main(String[] args) {
SoftReference<Object> softReference = new SoftReference<>(new Object());
System.out.println(softReference.get());
LinkedList<Integer[]> linkedList = new LinkedList<>();
try {
//故意制造内存泄露引发垃圾回收
while (linkedList.size() < 1024 * 1024) {
linkedList.add(new Integer[1024 * 1024]);
}
} catch (OutOfMemoryError error) {
System.out.println("发生内存泄露");
}
System.out.println(softReference.get());
}
java.lang.Object@1b6d3586
发生内存泄露
null
软引用适合用于实现内存敏感的高速缓存。
4.弱引用
弱引用的生命周期比软引用更短,当垃圾回收器下一次执行清理时,弱引用内存储的对象就会被回收;需要通过 java.lang.ref.WeakReference 来实现,使用方式同 SoftReference 。
如果你有一个对象偶尔会使用,又不想关注它的生命周期,便可以考虑使用 WeakReference 。
public static void main(String[] args) {
WeakReference<Object> weakReference = new WeakReference<>(new Object());
System.out.println(weakReference.get());
System.gc();
System.out.println(weakReference.get());
}
java.lang.Object@1b6d3586
null
5.虚引用
虛引用是引用关系最弱的一种,它随时都有可能被垃圾回收,需要通过 java.lang.ref.WeakReference 来实现,且必须搭配引用队列 java.lang.ref.ReferenceQueue 来使用;
通过查看 WeakReference 的源码,我们发现虚引用在任何时候都是返回 null,如同未持有任何对象;
那么虚引用有什么意义呢?当虚引用中持有的对象被垃圾回收后,引用队列 ReferenceQueue 会将 WeakReference 加入到其中,我们可以通过这种机制监听对象何时被清理,从而进行下一步操作。
public static void main(String[] args) throws InterruptedException {
Object o = new Object();
ReferenceQueue<Object> referenceQueue = new ReferenceQueue<Object>();
PhantomReference<Object> phantomReference = new PhantomReference<Object>(o, referenceQueue);
System.out.println(o);
//引用队列此时为空
System.out.println(referenceQueue.poll());
//虚引用永远返回null
System.out.println(phantomReference.get());
//将强引用释放
o = null;
//进行垃圾回收
System.gc();
//无法再次获取到object,phantomReference会被自动添加至referenceQueue
System.out.println(o);
//返回referenceQueue中的phantomReference
System.out.println(referenceQueue.poll());
//phantomReference依旧返回null
System.out.println(phantomReference.get());
}
java.lang.Object@1b6d3586
null
null
null
java.lang.ref.PhantomReference@4554617c
null
6.引用队列
引用队列 ReferenceQueue 可以配合软引用、弱引用、虚引用一同使用,虚引用是强制要求使用 ReferenceQueue ,软引用和弱引用则是可选的,当这几类引用中的持有对象被垃圾回收,它们被会自动添加至 ReferenceQueue ,从而达到监听对象回收的效果。
下例展示了 SoftReference和 WeakReference 配合 ReferenceQueue 的工作场景,当引用中的持有对象被回收时,才会被自动加入进 ReferenceQueue 中。
ReferenceQueue<Object> referenceQueue = new ReferenceQueue<>();
System.out.println("-----演示监听软引用被回收-----");
SoftReference<Object> softReference = new SoftReference<>(new Object(), referenceQueue);
System.out.println(referenceQueue.poll());
System.out.println(softReference.get());
LinkedList<Integer[]> linkedList = new LinkedList<>();
try {
//故意制造内存泄露引发垃圾回收
while (linkedList.size() < 1024 * 1024) {
linkedList.add(new Integer[1024 * 1024]);
}
} catch (OutOfMemoryError error) {
System.out.println("发生内存泄露");
System.out.println(referenceQueue.poll());
}
System.out.println(softReference.get());
System.out.println("-----演示监听弱引用被回收-----");
WeakReference<Object> weakReference = new WeakReference<>(new Object(), referenceQueue);
System.out.println(referenceQueue.poll());
System.out.println(weakReference.get());
System.gc();
System.out.println(weakReference.get());
System.out.println(referenceQueue.poll());
-----演示监听软引用被回收-----
null
java.lang.Object@1b6d3586
发生内存泄露
java.lang.ref.SoftReference@4554617c
null
-----演示监听弱引用被回收-----
null
java.lang.Object@74a14482
null
java.lang.ref.WeakReference@1540e19d
7.参考资料
资料名称 | 链接 |
---|---|
阿里面试: 说说强引用、软引用、弱引用、虚引用吧 | https://cloud.tencent.com/developer/article/1632413 |
Java 的强引用、弱引用、软引用、虚引用 | https://cloud.tencent.com/developer/article/1408097 |
本次分享至此结束,希望本文对你有所帮助,若能点亮下方的点赞按钮,在下感激不尽,谢谢您的【精神支持】。
若有任何疑问,也欢迎与我交流,若存在不足之处,也欢迎各位指正!
最后
以上就是端庄项链为你收集整理的强引用、软引用、弱引用、虚引用 --《JAVA编程思想》751.什么是引用?2.强引用3.软引用4.弱引用5.虚引用6.引用队列7.参考资料的全部内容,希望文章能够帮你解决强引用、软引用、弱引用、虚引用 --《JAVA编程思想》751.什么是引用?2.强引用3.软引用4.弱引用5.虚引用6.引用队列7.参考资料所遇到的程序开发问题。
如果觉得靠谱客网站的内容还不错,欢迎将靠谱客网站推荐给程序员好友。
发表评论 取消回复