参照:http://www.ibm.com/developerworks/cn/java/j-lo-langref/
1、解释
引用类型 | 取得目标对象方式 | 垃圾回收条件 | 是否可能内存泄漏 |
---|---|---|---|
强引用 | 直接调用 | 不回收 | 可能 |
软引用 | 视内存情况回收 | 不可能 | |
弱引用 | 通过 get() 方法 | 永远回收 | 不可能 |
虚引用 | 无法取得 | 不回收 | 可能 |
类型 | 是否抛出异常 | 示例代码 | 运行结果 |
---|---|---|---|
StrongReference | 抛出异常 | 见清单 6 | Exception in thread "main" java.lang.OutOfMemoryError: Java heap space |
SoftReference | 不抛异常,之前的引用自动清空并返回 null | 见清单 7 | null |
WeakReference | 同上 | 见清单 8 | null |
PhantomReference | 抛出异常 | 见清单 9 | Exception in thread "main" java.lang.OutOfMemoryError: Java heap space |
package cn.test.ref;
import java.lang.ref.PhantomReference;
import java.lang.ref.ReferenceQueue;
import java.lang.ref.SoftReference;
import java.lang.ref.WeakReference;
/**
* 测试各种引用
* 让我们来回顾一下四种引用类型的表现以及在垃圾回收器回收清理内存时的表现 .
* 1、软引用 (SoftReference), 引用类型表现为当内存接近满负荷 , 或对象由 SoftReference.get()
* 方法的调用没有发生一段时间后 , 垃圾回收器将会清理该对象 . 在运行对象的 finalize 方法前 , 会将软引用对象加入 ReferenceQueue 中去 .
* 2、弱引用 (WeakReference), 引用类型表现为当系统垃圾回收器开始回收时 , 则立即会回收该对象的引用 .
* 与软引用一样 , 弱引用也会在运行对象的 finalize 方法之前将弱引用对象加入 ReferenceQueue.
* 3、强引用 (FinalReference), 这是最常用的引用类型 . JVM 系统采用 Finalizer 来管理每个强引用对象 ,
* 并将其被标记要清理时加入 ReferenceQueue, 并逐一调用该对象的 finalize() 方法 .
* 4、虚引用 (PhantomReference), 这是一个最虚幻的引用类型 . 无论是从哪里都无法再次返回被虚引用所引用的对象 .
* 虚引用在系统垃圾回收器开始回收对象时 , 将直接调用 finalize() 方法 , 但不会立即将其加入回收队列 .
* 只有在真正对象被 GC 清除时 , 才会将其加入 Reference 队列中去 .
*/
public class TestKindsOfReference {
/****
*输出的结果
====================begin test softReference==================
RefTestObj:1没有执行回收
null
RefTestObj:1执行回收
====================end test softReference====================
====================begin test weakReference====================
RefTestObj:2没有执行回收
Object [6165421][id=2] come into finalize
Object [7100506][id=1] come into finalize
java.lang.ref.WeakReference@11ca803
null执行回收
====================end test weakReference====================
====================begin test phantomReference====================
null没有执行回收
Object [22266741][id=3] come into finalize
null
null
====================end test phantomReference====================
* @param args
*/
public static void main(String[] args) {
TestKindsOfReference tst = new TestKindsOfReference();
tst.testSoftReference();
tst.testWeakReference();
tst.testPhantomReference();
}
public void testSoftReference(){
System.out.println("====================begin test softReference==================");
RefTestObj refTestObj = new RefTestObj();
refTestObj.setId(1);
ReferenceQueue<RefTestObj> referenceQueue = new ReferenceQueue<RefTestObj>();
SoftReference<RefTestObj> softReference = new SoftReference<RefTestObj>(refTestObj,referenceQueue);
refTestObj = null;
System.out.println(softReference.get()+"没有执行回收");
System.gc();
System.runFinalization();
System.out.println(referenceQueue.poll());
System.out.println(softReference.get()+"执行回收");
System.out.println("====================end test softReference====================");
}
public void testWeakReference(){
System.out.println("====================begin test weakReference====================");
RefTestObj refTestObj = new RefTestObj();
refTestObj.setId(2);
ReferenceQueue<RefTestObj> referenceQueue = new ReferenceQueue<RefTestObj>();
WeakReference<RefTestObj> weakReference = new WeakReference<RefTestObj>(refTestObj,referenceQueue);
refTestObj = null;
System.out.println(weakReference.get()+"没有执行回收");
System.gc();
System.runFinalization();
System.out.println(referenceQueue.poll());
System.out.println(weakReference.get()+"执行回收");
System.out.println("====================end test weakReference====================");
}
/****
*1、采用虚引用,无论如何都取不到引用的对象:phantomReference.get()为null
*2、直接调用 finalize()
*3、只有在真正对象被 GC 清除时 , 才会将其加入 Reference 队列中去
*/
public void testPhantomReference(){
System.out.println("====================begin test phantomReference====================");
RefTestObj refTestObj = new RefTestObj();
refTestObj.setId(3);
ReferenceQueue<RefTestObj> referenceQueue = new ReferenceQueue<RefTestObj>();
PhantomReference<RefTestObj> phantomReference = new PhantomReference<RefTestObj>(refTestObj,referenceQueue);
refTestObj = null;
System.out.println(phantomReference.get()+"没有执行回收");
System.gc();
System.runFinalization(); //多次进行垃圾回收,有可能将对象加入到ReferenceQueue中
// System.gc();
// System.runFinalization();
// System.gc();
// System.runFinalization();
System.out.println(phantomReference.get()); //不管怎样都都无法取得
System.out.println(referenceQueue.poll());
System.out.println("====================end test phantomReference====================");
}
}