强引用
Object o = new Object();
o就是一个强引用, 强引用不会被VM GC, 即使
内存不够抛出OutOfMemoryError也不会被回收
软引用
/**对象不可达之后,一直到内存不足时,才被回收*/
class="java" name="code">
public class SoftReference<T> extends Reference<T> {...}
弱引用
/**对象不可达之后,gc运行就会被回收*/
public class WeakReference<T> extends Reference<T> {...}
虚引用
/**还没搞懂,构造的时候必须传一个ReferenceQueue*/
public class PhantomReference<T> extends Reference<T> {
...
public T get() {//但是PhantomReference的get方法,无论何时都返回的是null,这个接下来在看,,,多了怕记不住
return null;
}
}
还有WeakHashMap,之后再加上
Reference本身是一个链表的数据结构,有如下两个字段
private T referent;
Reference next;
Reference中 有个 静态的 pending字段
private static Reference pending = null;
vm会将不可达的Reference对象挂在pending链表上(VM实现);
Reference中还有个 ReferenceHandler 这个handler(Thread[Daemon
线程]),
在一个静态快中初始化,
功能就是
循环的访问pending,将pending中的不可达对象 入队(enqueue);
Reference & ReferenceQueue的关系:
Reference存在一个ReferenceQueue的引用,Reference存在一个ReferenceQueue的引用是在Reference的构造方法中初始化的,
如果没有指定,会传入一个
全局默认的queue但是这个默认的queue,但是这个queue 没有实际的入队操作(见下面源码),
如果传入一个构造的queue,不可达的对象会入队(enqueue)
class ReferenceQueue<T>{
//有两个静态的ReferenceQueue
static ReferenceQueue NULL = new Null();//默认的ReferenceQueue
static ReferenceQueue ENQUEUED = new Null();
private static class Null extends ReferenceQueue {
boolean enqueue(Reference r) {//Null 的enqueue()没有实际的入队操作
return false;
}
}
boolean enqueue(Reference<? extends T> r) { /* Called only by Reference class */
synchronized (r) {
if (r.queue == ENQUEUED) return false;
synchronized (lock) {
r.queue = ENQUEUED;
r.next = (head == null) ? r : head;
head = r;
queueLength++;
if (r instanceof FinalReference) {
sun.misc.VM.addFinalRefCount(1);
}
lock.notifyAll();
return true;
}
}
}
}
public abstract class Reference<T>{
...
private T referent;//构造函数传入(具体的对象)
ReferenceQueue<? super T> queue;
/*(网上看来的):pending是由jvm来赋值的,
当Reference内部的referent对象的可达状态改变时,
jvm会将Reference对象放入pending链表*/
private static Reference pending = null; /* used by VM */
...
/*守护线程,将注册在queue上,
不可达的referent(pending Reference 链表)放入 queue中*/
private static class ReferenceHandler extends Thread{
ReferenceHandler(ThreadGroup g, String name) {
super(g, name);
}
public void run() {
for (;;) {//对pending的访问
...
}
}
static { //初始化守护线程:ReferenceHandler
ThreadGroup tg = Thread.currentThread().getThreadGroup();
for (ThreadGroup tgn = tg;
tgn != null;
tg = tgn, tgn = tg.getParent());
Thread handler = new ReferenceHandler(tg, "Reference Handler");
/* If there were a special system-only priority greater than
* MAX_PRIORITY, it would be used here
*/
handler.setPriority(Thread.MAX_PRIORITY);
handler.setDaemon(true);
handler.start();
}
/**
* Adds this reference object to the queue with which it is registered,
* if any.*/
public boolean enqueue() {
return this.queue.enqueue(this);
}
...
}