Java中三个引用类SoftReference|Java中三个引用类SoftReference 、 WeakReference 和 PhantomReference的区别
转载:http://blog.csdn.net/mxbhxx/article/details/9111711
1. Strong Reference
StrongReference 是 Java 的默认引用实现,它会尽可能长时间的存活于 JVM 内, 当没有任何对象指向它时 GC 执行后将会被回收
1.@Test
2.public void strongReference() {
3.Object referent = new Object();
5./**
6.* 通过赋值创建 StrongReference
7.*/
8.Object strongReference = referent;
10.assertSame(referent, strongReference);
12.referent = null;
13.System.gc();
15./**
16.* StrongReference 在 GC 后不会被回收
17.*/
18.assertNotNull(strongReference);
19.}
2. WeakReference & WeakHashMap
WeakReference, 顾名思义, 是一个弱引用, 当所引用的对象在 JVM 内不再有强引用时, GC 后 weak reference 将会被自动回收
1.@Test
2.public void weakReference() {
3.Object referent = new Object();
4.WeakReference
WeakHashMap 使用 WeakReference 作为 key, 一旦没有指向 key 的强引用, WeakHashMap 在 GC 后将自动删除相关的 entry
1.@Test
2.public void weakHashMap() throws InterruptedException {
3.Map weakHashMap = new WeakHashMap();
4.Object key = new Object();
5.Object value = https://www.it610.com/article/new Object();
6.weakHashMap.put(key, value);
8.assertTrue(weakHashMap.containsValue(value));
10.key = null;
11.System.gc();
13./**
14.* 等待无效 entries 进入 ReferenceQueue 以便下一次调用 getTable 时被清理
15.*/
16.Thread.sleep(1000);
18./**
19.* 一旦没有指向 key 的强引用, WeakHashMap 在 GC 后将自动删除相关的 entry
20.*/
21.assertFalse(weakHashMap.containsValue(value));
22.}
3. SoftReference
SoftReference 于 WeakReference 的特性基本一致, 最大的区别在于 SoftReference 会尽可能长的保留引用直到 JVM 内存不足时才会被回收(虚拟机保证), 这一特性使得 SoftReference 非常适合缓存应用
1.@Test
2.public void softReference() {
3.Object referent = new Object();
4.SoftReference softRerference = new SoftReference(referent);
6.assertNotNull(softRerference.get());
8.referent = null;
9.System.gc();
11./**
12.*soft references 只有在 jvm OutOfMemory 之前才会被回收, 所以它非常适合缓存应用
13.*/
14.assertNotNull(softRerference.get());
15.}
4. PhantomReference
最关键的来了, Phantom Reference(幽灵引用) 与 WeakReference 和 SoftReference 有很大的不同,因为它的 get() 方法永远返回 null, 这也正是它名字的由来
1.@Test
2.public void phantomReferenceAlwaysNull() {
3.Object referent = new Object();
4.PhantomReference phantomReference = new PhantomReference(referent, new ReferenceQueue());
6./**
7.* phantom reference 的 get 方法永远返回 null
8.*/
9.assertNull(phantomReference.get());
10.}
诸位可能要问, 一个永远返回 null 的 reference 要来何用, 请注意构造 PhantomReference 时的第二个参数 ReferenceQueue(事实上 WeakReference & SoftReference 也可以有这个参数),
PhantomReference 唯一的用处就是跟踪 referent 何时被 enqueue 到 ReferenceQueue 中.
5. RererenceQueue
当一个 WeakReference 开始返回 null 时, 它所指向的对象已经准备被回收, 这时可以做一些合适的清理工作. 将一个 ReferenceQueue 传给一个 Reference 的构造函数, 当对象被回收时, 虚拟机会自动将这个对象插入到 ReferenceQueue 中, WeakHashMap 就是利用 ReferenceQueue 来清除 key 已经没有强引用的 entries.
Java代码
文章图片
收藏代码
1.@Test
2.public void referenceQueue() throws InterruptedException {
3.Object referent = new Object();
4.ReferenceQueue referenceQueue = new ReferenceQueue();
5.WeakReference weakReference = new WeakReference(referent, referenceQueue);
7.assertFalse(weakReference.isEnqueued());
8.Reference extends Object> polled = referenceQueue.poll();
9.assertNull(polled);
11.referent = null;
12.System.gc();
14.assertTrue(weakReference.isEnqueued());
15.Reference extends Object> removed = referenceQueue.remove();
16.assertNotNull(removed);
17.}
- PhantomReference vs WeakReference
【Java中三个引用类SoftReference|Java中三个引用类SoftReference 、 WeakReference 和 PhantomReference的区别】其二, 它可以避免 finalization 带来的一些根本性问题, 上文提到 PhantomReference 的唯一作用就是跟踪 referent 何时被 enqueue 到 ReferenceQueue 中, 但是 WeakReference 也有对应的功能, 两者的区别到底在哪呢 ?
这就要说到 Object 的 finalize 方法, 此方法将在 gc 执行前被调用, 如果某个对象重载了 finalize 方法并故意在方法内创建本身的强引用, 这将导致这一轮的 GC 无法回收这个对象并有可能
引起任意次 GC, 最后的结果就是明明 JVM 内有很多 Garbage 却 OutOfMemory, 使用 PhantomReference 就可以避免这个问题, 因为 PhantomReference 是在 finalize 方法执行后回收的,也就意味着此时已经不可能拿到原来的引用, 也就不会出现上述问题, 当然这是一个很极端的例子, 一般不会出现.
- 小结
一般的应用程序不会涉及到 Reference 编程, 但是了解这些知识会对理解 GC 的工作原理以及性能调优有一定帮助, 在实现一些基础性设施比如缓存时也可能会用到, 希望本文能有所帮助.
推荐阅读
- 热闹中的孤独
- JAVA(抽象类与接口的区别&重载与重写&内存泄漏)
- 放屁有这三个特征的,请注意啦!这说明你的身体毒素太多
- Shell-Bash变量与运算符
- JS中的各种宽高度定义及其应用
- 2021-02-17|2021-02-17 小儿按摩膻中穴-舒缓咳嗽
- 深入理解Go之generate
- 异地恋中,逐渐适应一个人到底意味着什么()
- 我眼中的佛系经纪人
- 《魔法科高中的劣等生》第26卷(Invasion篇)发售