`
shifulong
  • 浏览: 59631 次
  • 性别: Icon_minigender_1
  • 来自: 北京
社区版块
存档分类
最新评论

Reference ReferenceQueue WeakHashMap详解

    博客分类:
  • java
阅读更多
强引用
Object o = new Object();
o就是一个强引用, 强引用不会被VM GC, 即使内存不够抛出OutOfMemoryError也不会被回收

软引用
/**对象不可达之后,一直到内存不足时,才被回收*/
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);
    }
	...
}

接下来是WeakHashMap
public class WeakHashMap<K,V> extends AbstractMap<K,V> implements Map<K,V> {
....
    /*在WeakHashMap则在内部提供了一个非NULL的ReferenceQueue*/
    /*WeakHashMap的实现也是通过ReferenceQueue这个“监听器”来实现自动删除那些引用不可达的key的*/
	private final ReferenceQueue<Object> queue = new ReferenceQueue<>();
	
	/*内部类,实体,继承WeakReference,重要的是构造方法*/
	private static class Entry<K,V> extends WeakReference<Object> implements Map.Entry<K,V> {
	    V value;
        int hash;
        Entry<K,V> next;
	    Entry(Object key, V value,ReferenceQueue<Object> queue,
              int hash, Entry<K,V> next) {
			/*把key放入 WeakReference 的 private T referent; 
			  WeakHashMap的key会被回收,但是value却不会被回收,
			  但是 通过调用 expungeStaleEntries(),value会被回收
			  源码如下*/
            super(key, queue);
            this.value = value;
            this.hash  = hash;
            this.next  = next;
        }
	....
	}
	
    /*核心的方法*/
    private void expungeStaleEntries() {
        for (Object x; (x = queue.poll()) != null; ) {
            synchronized (queue) {
                @SuppressWarnings("unchecked")
                    Entry<K,V> e = (Entry<K,V>) x;
                int i = indexFor(e.hash, table.length);

                Entry<K,V> prev = table[i];
                Entry<K,V> p = prev;
                while (p != null) {
                    Entry<K,V> next = p.next;
                    if (p == e) {
                        if (prev == e)
                            table[i] = next;
                        else
                            prev.next = next;
                        // Must not null out e.next;
                        // stale entries may be in use by a HashIterator
                        e.value = null; // Help GC
                        size--;
                        break;
                    }
                    prev = p;
                    p = next;
                }
            }
        }
    }
}
分享到:
评论

相关推荐

    详解Java对象的强、软、弱和虚引用+ReferenceQueue

    ReferenceQueue是一个引用队列,如果保存的是Reference对象本身,如果:Reference引用指向的对象被GC回收,其实Reference已经无效了这种Reference将被放入引用队列,可以在这里将其清除,避免占有空间。 六、...

    Java 中 Reference用法详解

    Java 中 Reference 用法详解 Java 中的 Reference 类型主要分为四种:强引用、软引用、弱引用和虚引用。这些引用类型在 Java 中的使用非常广泛,特别是在缓存、池化和垃圾回收机制中。 强引用(Strong Reference)...

    Java功底之Reference

    在Java编程语言中,`Reference`类是一个非常特殊且重要的概念,它超出了常规的引用类型,如`Object`或数组引用。`Reference`类及其子类主要用于处理对象的软引用、弱引用和虚引用,这些引用类型在内存管理,特别是...

    详解java中Reference的实现与相应的执行过程

    2. `Reference(T referent, ReferenceQueue&lt;? super T&gt; queue)`:创建一个关联指定队列的引用对象。当对象将要被回收时,引用对象会被添加到队列中,便于外部监控。 `NULL` 队列是一个特殊队列,不会保存任何数据,...

    Java中几个Reference常见的作用详解

    `WeakReference`常用于实现弱集合,如`WeakHashMap`,这样可以避免因集合中的元素导致对象无法被回收。 3. **SoftReference**: 软引用在内存管理策略上介于强引用和弱引用之间。当系统内存不足但尚未达到OOM状态...

    Java编程WeakHashMap实例解析

    当垃圾回收器清理对象时,会将对象的引用添加到ReferenceQueue中,这样可以使得WeakHashMap自动清理键和值。 WeakHashMap的使用场景有很多,例如缓存、线程安全等。在缓存中,WeakHashMap可以用来存储缓存的数据,...

    Java Reference源码解析

    5. 引用队列(ReferenceQueue):该队列作为引用中的一员,可以和上述三种引用类型组合使用,该队列的作用是:创建Reference时,将Queue注册到Reference中,当该Reference所引用的对象被垃圾收集器回收时,会将该...

    Java引用类型1

    【Java 引用类型详解】 在Java编程语言中,引用类型是内存管理的一个重要概念,它允许程序员对对象的生命周期进行一定程度的控制。Java提供了四种不同级别的引用类型:强引用、软引用、弱引用和虚引用(幻象引用)...

    Java引用总结--StrongReference、SoftReference、WeakReference、PhantomRef

    Java从1.2版本开始引入了四种引用,分别是强引用(StrongReference)、软引用(SoftReference)、弱引用(WeakReference)和虚引用(PhantomReference)。这四种引用的级别由高到低依次为:强引用 &gt; 软引用 &gt; 弱引用...

    从面试题中看java的Reference(引用)

    软引用通常与ReferenceQueue结合使用,清除后的软引用会被放入队列中。软引用的对象在系统抛出`OutOfMemoryError`之前一定会被清理。 3. 弱引用(Weak Reference): 弱引用比软引用更弱,它所引用的对象在下一次...

    Java中的软引用弱引用和虚引用.docx

    ### Java中的软引用、弱引用和虚引用详解 #### 一、引言 在Java开发过程中,特别是Android应用开发中,经常会遇到一个普遍的问题——内存溢出(OutOfMemory Error,简称OOM)。这个问题往往与如何有效地管理内存...

    java 引用相关文档

    这使得弱引用常用于实现内存敏感的数据结构,如`WeakHashMap`。 - 示例:`WeakReference&lt;String&gt; weakRef = new WeakReference(new String("Hello"));` 4. **虚引用(Phantom Reference)** - 虚引用也称为幽灵...

    Java的四种引用

    ### Java的四种引用详解 #### 一、引言 从JDK 1.2版本开始,Java引入了一种更为精细的引用类型管理机制,通过四种不同的引用类型:强引用、软引用、弱引用和虚引用,让开发者能够更加灵活地控制对象的生命周期。...

    jdk 1.6 gc详解

    Weak引用在被标记为dead后会在ReferenceQueue中通知。Phantom引用的对象在从JVM堆中释放时会被通知。 为了提高GC的效率,Hotspot JVM采用了分代收集策略,将堆分为新生代(包括Eden、S0和S1)和老年代(Old ...

    线程池调用队列

    线程池调用队列是多线程编程中一个重要的概念,它在处理并发任务时起着关键作用。线程池是一种高效的线程管理机制,它通过预先创建一定数量的线程来处理任务,而不是每次需要执行任务时都创建新线程。...

    Java中的强软弱虚引用

    ### Java中的强软弱虚引用详解 #### 一、引言 在Java中,对象的生命周期与内存管理密切相关。为了更好地理解和控制对象的生命周期,Java提供了四种不同类型的引用:强引用(Strong Reference)、软引用(Soft ...

    程序避免被GC 回收 --------引用

    ReferenceQueue&lt;Bitmap&gt; queue = new ReferenceQueue(); SoftReference&lt;Bitmap&gt; softRef = new SoftReference(bitmap, queue); // 检查引用队列 if (queue.poll() != null) { // 执行清理操作 } ``` 以上就是关于...

    smartref:Java 1.5+ 的简单引用类型和容器

    这些智能引用类型配合相应的容器类,如`java.lang.ref.ReferenceQueue`和`java.util.WeakHashMap`,可以在特定场景下实现高效和灵活的对象管理。例如,`WeakHashMap`中的键使用弱引用,当键的对象被垃圾收集时,键值...

    Java基础总结下1

    Reference和ReferenceQueue可以实现对象的软引用、弱引用和虚引用,用于内存管理。 总的来说,Java的基础知识体系广泛且深入,涵盖了从基本语法、输入输出、集合框架到高级特性的方方面面,对于开发者来说,理解和...

Global site tag (gtag.js) - Google Analytics