java四种引用类型总结

/ java / 没有评论 / 919浏览

强引用

/*
 * 这样普通的列出来就是强引用
 */
Object obj = new Object();

软引用

Object obj1 = new Object();

/*
 * 软引用
 * 用来实现一些内存敏感的缓存(Soft references are for 
 * implementing memory-sensitive caches),只要内存
 * 空间足够,对象就会保持不被回收.
 *
 * 当宿主进程的内存空间不足时,对象就会被GC回收。
 */
ReferenceQueue<Object> queueSoft = new ReferenceQueue<>();
SoftReference<Object> softReference = new SoftReference<>(obj1, queueSoft);

弱引用

Object obj2 = new Object();
/*
 * 弱引用
 *
 * WeakReference可以用来实现一些规范化映射(WeakHashMap),其
 * 中key或者value当它们不再被引用时
 * 可以自动被回收.
 * 当你想引用一个对象,但是这个对象有自己的生命周期,你不想介入这个
 * 对象的生命周期这时候就可以使用弱引用.
 * 这个引用不会在对象的垃圾回收判断中产生任何附加的影响.
 */
ReferenceQueue<Object> queueWeak = new ReferenceQueue<>();
WeakReference<Object> weakReference = new WeakReference<>(obj2, queueWeak);

虚引用

这个虚引用用到了我自定义的一个Object类。

public class TestOject extends Object {
    @Override
    protected void finalize() throws Throwable {
        super.finalize();
        System.out.println("method finalize() execute");
    }
}

下面是具体的虚引用记录。

Object obj3 = new TestOject();

/*
 * 虚引用
 * PlantomReference和WeakReference一样,也不会介入引用对象的生命周期.
 * PlantomReference比较特殊,它的get方法总是返回null,所以你得不到它引
 * 用的对象.
 *
 * 虚引用主要是用来跟踪对象被垃圾回收的状态,通过查看引用队列中是否包含对
 * 象对应的虚引用来判断它是否即将被垃圾回收。
 *
 * 很重要的一点:虚引用不会根据内存情况自动回收目标对象!!
 * 因此虚引用可能发生内存泄露的情况!!!
 */
ReferenceQueue<Object> queuePlantom = new ReferenceQueue<>();
PhantomReference<Object> phantomReference = 
        new PhantomReference<>(obj3, queuePlantom);

log("normal obj3: " + obj3);
log("phantom reference: " + phantomReference);

log("phantom reference method get(): " + phantomReference.get());
log("reference queue method poll(): " + queuePlantom.poll());

log("phantom reference is enqueued? : " + phantomReference.isEnqueued());

obj3 = null;
/*
 * 这里只是建议java虚拟机去执行gc
 */
System.gc();
log("first gc....");
try {
    Thread.sleep(5000);
} catch (InterruptedException e) {
    e.printStackTrace();
}

log("phantom reference method get(): " + phantomReference.get());

Reference<?> poll = queuePlantom.poll();
log("reference queue method poll(): " + poll);
log("phantom reference is enqueued? : " + phantomReference.isEnqueued());

/*
 * 这里再次建议建议java虚拟机去执行gc
 */
System.gc();

/*
 * 这个方法时建议java虚拟机去执行有些对象中的finalize()方法。前
 * 提是这个对象中的finalize方法没有被执行过。
 */
//System.runFinalization();
log("second gc....");
try {
    Thread.sleep(2000);
} catch (InterruptedException e) {
    e.printStackTrace();
}

/*
 * 当系统执行过gc后obj3并没有立即被回收,系统而是将phantomReference插
 * 入到queuePlantom这个队列中。
 * 当再次调用queuePlantom.poll()方法时返回phantomReference对象。poll
 * 方法会先把phantomReference的
 * 持有队列queue(ReferenceQueue<? super T>)置为NULL,NULL对象继承
 * 自ReferenceQueue,
 * NULL对象的enqueue(Reference paramReference)方法一直返回return false。
 *
 * 注意将phantomReference插入到queuePlantom这个队列中的操作的时间是不受
 * 我们控制的,由java虚拟机控制。
 *
 * 我们判断obj3是否被垃圾回收就应该判断queuePlantom.poll()返回的对象引
 * 用是否为obj3。
 */
log("reference queue method poll(): " + queuePlantom.poll());
log("phantom reference is enqueued? : " + phantomReference.isEnqueued());


printInfo(phantomReference);

/*
 * 要手动调用clear()方法来清除包含的引用
 */
phantomReference.clear();

printInfo(phantomReference);
        

下面是虚引用相关的log输出。

normal obj3: org.tuzhao.reference.TestOject@330bedb4
phantom reference: java.lang.ref.PhantomReference@2503dbd3
phantom reference method get(): null
reference queue method poll(): null
phantom reference is enqueued? : false
first gc....
method finalize() execute
phantom reference method get(): null
reference queue method poll(): null
phantom reference is enqueued? : false
second gc....
reference queue method poll(): java.lang.ref.PhantomReference@2503dbd3
phantom reference is enqueued? : false
print info start
filed : referent value: org.tuzhao.reference.TestOject@330bedb4
filed : queue value: java.lang.ref.ReferenceQueue$Null@7ea987ac
filed : next value: java.lang.ref.PhantomReference@2503dbd3
filed : discovered value: null
filed : lock value: java.lang.ref.Reference$Lock@29453f44
filed : pending value: null
print info end

print info start
filed : referent value: null
filed : queue value: java.lang.ref.ReferenceQueue$Null@7ea987ac
filed : next value: java.lang.ref.PhantomReference@2503dbd3
filed : discovered value: null
filed : lock value: java.lang.ref.Reference$Lock@29453f44
filed : pending value: null
print info end


Process finished with exit code 0