今天在看 blog 的时候学习到了 java reference 方面的知识,这些知识是个人的学习笔记,参考blog为:
http://www.ibm.com/developerworks/cn/java/j-lo-langref/index.html?ca=drs-希望各位能拍砖,让我能了解到更深入的内容以及不足,感激
StrongReference :
我们知道,当你调用例如
String test = new String(“test”);
(PS: 这里只是代码实例,千万不要这么写代码,因为这是 s tupid 的,会浪费内存空间 ) 的时候, test 在这里是 StrongReference 的,是强引用,强引用可以直接访问目标对象,
强引用所指向的对象在任何时候都不会被系统回收,强引用可能导致内存泄漏。所以如果你要设计一个 java 缓存系统,可以考虑少使用强引用,因为这样会让你的程序在无法预知的情况下出现 oom ,而缓存化是可以允许数据丢失,而去持久化层拿数据的。
强引用的特点:
(1) 强引用可以直接访问目标对象。
(2) 强引用所指向的对象在任何时候都不会被系统回收。
(3) 强引用可能导致内存泄漏。
SoftReference :
SoftReference 所指向的对象,在没有强引用指向的情况下,是可以被 jvm 回收的, gc 会根据当前的内存使用情况,以及 SoftReference 的 get() 方法的调用情况来决定是否回收,这与 WeakReference 是有很大区别的,下面的代码实例可以看出。
SoftReference 特点:
(1) 软引用使用 get() 方法取得对象的强引用从而访问目标对象。
(2) 软引用所指向的对象按照 JVM 的使用情况( Heap 内存是否临近阈值)来决定是否回收。
(3) 软引用可以避免 Heap 内存不足所导致的异常。
当垃圾回收器决定对其回收时,会先清空它的 SoftReference ,也就是说 SoftReference 的 get() 方法将会返回 null ,然后再调用对象的 finalize() 方法,并在下一轮 GC 中对其真正进行回收。
WeakReference :
WeakReference 与 SoftReference 的调用方法基本相同,但是弱与 SoftReference , WeakReference 所指向的对象只要进行系统垃圾回收,不管内存使用情况如何,永远对其进行回收( get() 方法返回 null )。
WeakReference 特点:
(1) 弱引用使用 get() 方法取得对象的强引用从而访问目标对象。
(2) 一旦系统内存回收,无论内存是否紧张,弱引用指向的对象都会被回收。
(3) 弱引用也可以避免 Heap 内存不足所导致的异常。
Soft&Weak 代码实例:
package com.taobao.reference.test;
import java.lang.ref.PhantomReference;
import java.lang.ref.SoftReference;
import java.lang.ref.WeakReference;
import org.junit.Test;
public class AllReferenceTest {
private static final SoftReference<TestBean> softTest =
new SoftReference<TestBean>(new TestBean("soft"));
private static final WeakReference<TestBean> weakTest =
new WeakReference<TestBean>(new TestBean("weak"));
/*private PhantomReference<TestBean> phantomTest =
new PhantomReference<TestBean>(new TestBean("weak"));*/
@Test
public void soft_test_method(){
System.gc();
// 这里你会得到你想要的结果
System.out.println(softTest.get().getName());
}
@Test
public void weak_test_method(){
//System.gc();
// 这里你也会得到你想要的结果,但是将 gc 的注释去掉之后,你会发现
// 返回 null 了,这就是 Weak 和 Soft 的区别。
System.out.println(weakTest.get().getName());
}
static class TestBean{
private String name;
public TestBean(String name) {
this.name = name;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
}
}
PhantomReference :
PhantomReference 当你调用它的 get 方法的时候,你会发现一只为 null ,那么它是干神马用的呢?它其实是用来跟踪对象被垃圾回收的状态,通过查看引用队列中是否包含对象所对应的虚引用来判断它是否即将被垃圾回收,从而采取行动。
代码实例:
public static void main(String[] args) {
ReferenceQueue<String> refQueue = new ReferenceQueue<String>();
PhantomReference<String> referent = new PhantomReference<String>(
new String("T"), refQueue);
System.out.println(referent.get());// null
System.gc();
System.runFinalization();
System.out.println(refQueue.poll() == referent); //true
}
特点:
(1) 虚引用永远无法使用 get() 方法取得对象的强引用从而访问目标对象。
(2) 虚引用所指向的对象在被系统内存回收前,虚引用自身会被放入 ReferenceQueue 对象中从而跟踪对象垃圾回收。
(3) 虚引用不会根据内存情况自动回收目标对象。
注意的地方:
其实 SoftReference, WeakReference 以及 PhantomReference 的构造函数都可以接收一个 ReferenceQueue 对象。当 SoftReference 以及 WeakReference 被清空的同时,也就是 Java 垃圾回收器 准备 对它们所指向的对象进行回收时,调用对象的 finalize() 方法之前,它们自身会被加入到这个 ReferenceQueue 对象中,此时可以通过 ReferenceQueue 的 poll() 方法取到它们。而 PhantomReference 只有当 Java 垃圾回收器对其所指向的对象 真正进行回收 时,会将其加入到这个 ReferenceQueue 对象中,这样就可以追综对象的销毁情况。