java.lang.ref.Reference源代码分析

自己想学习下java.lang.ref这个package下面的源码,在网上找了找一些帖子看了看,感觉对自己的帮助很大,打算自己总结下java.lang.ref这个包,以及垃圾回收的机制,期待对自己有帮助.

一,引用实例有4个状态,Active,Pending,Enqueued,Inactive.jdk源码的解释如下:

  • Active: Subject to special treatment by the garbage collector. Some time after the collector detects that the reachability of the referent has changed to the appropriate state, it changes the instance’s state to either Pending or Inactive, depending upon whether or not the instance was registered with a queue when it was created. In the former case it also adds the instance to the pending-Reference list. Newly-created instances are Active.
      激活:垃圾回收器特别处理的主题。有时候在回收器检测到被引用(对象)的可达性被改变成适当 的状态,它会把实例的状态改变成等待状态或者未激活状态,这取决于实例是否被一个队列注册当 它被创建。在前一种情况下(等待状态),它也往等待-引用集合增加实例。
  • Pending: An element of the pending-Reference list, waiting to be enqueued by the Reference-handler thread. Unregistered instances are never in this state.
      等待:一个等待-引用集合里的元素,等待被引用处理线程放入队列中。
      未注册的实例永远不会在这个状态
  • Enqueued: An element of the queue with which the instance was registered when it was created. When an instance is removed from its ReferenceQueue, it is made Inactive. Unregistered instances are never in this state.
      入队:实例被创建的时候被登记注册成一个队列的元素。当一个实例从引用队列中删除,它变成非激活状态。未注册的实例永远不会在这个状态。
  • Inactive: Nothing more to do. Once an instance becomes Inactive its state will never change again.
      非激活:不会再做什么。一旦一个实例成为非激活的,它的状态永远不会被改变。
      The state is encoded in the queue and next fields as follows:

二,状态在队列里被处理并且每个状态所表现的属性如下:

  • Active: queue = ReferenceQueue with which instance is registered, or
    ReferenceQueue.NULL if it was not registered with a queue; next =
    null.
    激活:queue=引用队列时候,实例被它注册, 或者实例不被注册,当queue=ReferenceQueue.NULL时候; next=null.
  • Pending: queue = ReferenceQueue with which instance is registered; next = Following instance in queue, or this if at end of list.
    等待:queue=引用队列时候,实例被它注册, next=剩下的queue队列里面的实例,或者=this,如果this是队列的最后一个。
  • Enqueued: queue = ReferenceQueue.ENQUEUED; next = Following instance
    in queue, or this if at end of list.
    入队:queue=ReferenceQueue.ENQUEUED , next=剩下的queue队列里面的实例,或者=this,如果this是队列的最后一个
  • Inactive: queue = ReferenceQueue.NULL; next = this.
    终止:队列=ReferenceQueue.NULL next=this

    三,成员变量

    private T referent; // 被GC引用的对象
    volatile ReferenceQueue queue; //引用队列
    Reference next; //下个引用
    transient private Reference discovered; ///被VM引用的瞬态对象
    //GC线程在回收的时候的锁
    // 对象被用来和GC同步。GC必须获得锁在每个回收的生命周期。
    // 更关键的是任何持有锁的代码尽可能快的执行完,没有分配新的对象,并避免使用使用者的代码。
    static private class Lock { }
    private static Lock lock = new Lock();
    // 排队的引用集合。当处理引用的线程删除引用时候,收集器添加引用到这个集合。
    这个集合受上面的对象锁保护。
    private static Reference pending = null;

如何处理pending的

1 : tryHandlePending

static boolean tryHandlePending(boolean waitForNotify) {
        Reference<Object> r;
        Cleaner c;
        try {
            synchronized (lock) {
                if (pending != null) {
                    r = pending;
                    c = r instanceof Cleaner ? (Cleaner) r : null;
                    pending = r.discovered;
                    r.discovered = null;
                } else {
                    if (waitForNotify) {
                        lock.wait();
                    }
                    return waitForNotify;
                }
            }
        } catch (OutOfMemoryError x) {
            Thread.yield();
            return true;
        } catch (InterruptedException x) {
            // retry
            return true;
        }
        if (c != null) {
            c.clean();
            return true;
        }
        ReferenceQueue<? super Object> q = r.queue;
        if (q != ReferenceQueue.NULL) q.enqueue(r);
        return true;
    }
    ```
    pending != null时候,pending赋值给r, discovered赋值给pending,discovered等于null
    如果r.的queue不为空时候,放入Queue中
static {
    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();

    // provide access in SharedSecrets
    SharedSecrets.setJavaLangRefAccess(new JavaLangRefAccess() {
        @Override
        public boolean tryHandlePendingReference() {
            return tryHandlePending(false);
        }
    });
}

“`
去起来一个守护进程,来搞tryHandlePending
java.lang.ref.Reference
有些问题,自己也不太明白(先这样记录下),如果又错误,请留言.

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章