java.lang.ref包
所属分类 jvm
浏览量 1336
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进程分析方法汇总