首页  

java.lang.ref包     所属分类 jvm 浏览量 94
java.lang.ref.Finalizer.class
java.lang.ref.FinalReference.class
java.lang.ref.PhantomReference.class
java.lang.ref.Reference.class
java.lang.ref.ReferenceQueue.class
java.lang.ref.SoftReference.class
java.lang.ref.WeakReference.class


四种引用类型
strong soft weak Phantom

final class Finalizer extends FinalReference< Object>
ReferenceQueue

private static class FinalizerThread extends Thread



Reference要点
四种引用类型
两个队列 pending与ReferenceQueue
Pending队列数据来源
ReferenceHander线程的处理过程 ,如何将Pending与ReferenceQueue关联起来



    Reference(T referent) {
        this(referent, null);
    }

    Reference(T referent, ReferenceQueue< ? super T> queue) {
        this.referent = referent;
        this.queue = (queue == null) ? ReferenceQueue.NULL : queue;
    }
    
    

Reference 对象4种状态及转换

Active    对象存在强引用状态,还没有被回收
Pending   GC将没有强引用的Reference对象放入到pending队列中,等待ReferenceHander线程处理(前提是这个Reference对象创建的时候传入了ReferenceQueue,否则直接进入Inactive状态) 
Enqueued  ReferenceHander线程将pending队列中的对象取出来放到ReferenceQueue队列里
Inactive  处于此状态的Reference对象可以被回收,并且其内部封装的对象也可以被回收掉 

创建时没有传入ReferenceQueue的Reference对象,被Reference封装的对象在没有强引用时,指向它的Reference对象直接进入Inactive状态
Reference对象经过前面三个状态后,已经由外部从ReferenceQueue中获取到,并且处理掉了


ReferenceHandler线程是拥有最高优先级的守护线程,是Reference类的一个内部类,
在Reference类加载执行cinit的时候被初始化并启动;
遍历 pending队列 ,如果这个对象是个Cleaner实例,直接执行clean方法来执行清理工作,否则放入ReferenceQueue里面

ReferenceHandler线程 是pending队列与ReferenceQueue的桥梁
High-priority thread to enqueue pending References



"Finalizer" #3 daemon prio=8 os_prio=31 tid=0x00007f988c820000 nid=0x3003 in Object.wait() [0x000070000092e000]
"Reference Handler" #2 daemon prio=10 os_prio=31 tid=0x00007f988d81e000 nid=0x2e03 in Object.wait() [0x000070000082b000]


Finalizer线程

static {
        ThreadGroup tg = Thread.currentThread().getThreadGroup();
        for (ThreadGroup tgn = tg;
             tgn != null;
             tg = tgn, tgn = tg.getParent());
        Thread finalizer = new FinalizerThread(tg);
        finalizer.setPriority(Thread.MAX_PRIORITY - 2);
        finalizer.setDaemon(true);
        finalizer.start();
    }


JVM进行GC时,首先使用可达性分析算法,找出不在GC Roots引用链上的对象,
这时进行一次标记(标记出需要回收的对象)并筛选(对需要回收对象进行筛选),筛选条件就是是否有必要执行finalize方法。
当对象没有覆盖或已执行过finalize方法,则没有必要执行;
否则将对象放到由JVM创建的Finalizer线程维护的F-Queue(java.lang.ref.Finalizer.ReferenceQueue)队列中,
Finalizer线程会遍历执行队列中对象的finalize方法,只有当F-Queue中对象finalize执行完成后,
并且下次GC时可达性分析不再GC Roots的引用链上,这些对象占用的内存才能被真正回收。

Finalizer线程处理对象的速度小于创建对象的速度时,会造成F-Queue越来越大,JVM内存无法及时释放

一般不需要重写finalize  ,不推荐使用
单线程 执行 finalize  ,会有性能问题, 导致 GC 效率低下

finalize 方法的缺点
可能错误导致对象复活
finalize 执行时间不确定 
finalize 单线程 ,影响GC性能


finalize 使用场景
需要通过native方法来释放资源
比如   FileInputStream  socket  AbstractPlainSocketImpl 等



四种引用及WeakHashMap介绍 软引用弱引用及引用队列实战例子

上一篇     下一篇
获取jvm heap dump 的几种方式

MAT内存泄露分析实战

MAT内存分析之OQL

http2.0简介

ps aux -aux -ef之间的区别

linux进程分析方法汇总