博客
关于我
强烈建议你试试无所不能的chatGPT,快点击我
Guava Finalizer
阅读量:6414 次
发布时间:2019-06-23

本文共 8074 字,大约阅读时间需要 26 分钟。

/* * Copyright (C) 2008 The Guava Authors Licensed under the Apache License, Version 2.0 (the "License"); you may not use * this file except in compliance with the License. You may obtain a copy of the License at * http://www.apache.org/licenses/LICENSE-2.0 Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, * either express or implied. See the License for the specific language governing permissions and limitations under the * License. */package com.google.common.base.internal;import java.lang.ref.PhantomReference;import java.lang.ref.Reference;import java.lang.ref.ReferenceQueue;import java.lang.ref.WeakReference;import java.lang.reflect.Field;import java.lang.reflect.Method;import java.util.logging.Level;import java.util.logging.Logger;/** * Thread that finalizes referents. All references should implement {
@code com.google.common.base.FinalizableReference}. * * 用来清理被引用对象.所有的引用必须实现FinalizableReference * *

* While this class is public, we consider it to be *internal* and not part of our published API. It is public so we can * access it reflectively across class loaders in secure environments. * * 当这个类是public时,我们将其作为internal而非published的API.因为他是public的所以我们可以在一个安全的环境中通过class loaders反射地来访问他 * *

* This class can't depend on other Google Collections code. If we were to load this class in the same class loader as * the rest of Google Collections, this thread would keep an indirect strong reference to the class loader and prevent * it from being garbage collected. This poses a problem for environments where you want to throw away the class loader. * For example, dynamically reloading a web application or unloading an OSGi bundle. * * 这个类不能依赖于其他Google Collections代码.假如我们像其他Google Collections那样在同一个class loader中载入这个类,这个线程会保留一个 * 间接的强引用到class loader上并阻止他被垃圾回收.这会在当你想丢弃这个class loader的时候造成一个问题.例如,动态的重新载入一个web应用程序或者 * 卸载一个osgi bundle * *

* {

@code com.google.common.base.FinalizableReferenceQueue} loads this class in its own class loader. That way, this * class doesn't prevent the main class loader from getting garbage collected, and this class can detect when the main * class loader has been garbage collected and stop itself. * * FinalizableReferenceQueue使用它自己的class loader加载这个类,也就是说这个类不会阻止主class loader被垃圾回收,并且这个在检测到主 * class loader被垃圾回收后会停止他自己 */public class Finalizer implements Runnable { private static final Logger logger = Logger.getLogger(Finalizer.class.getName()); /** Name of FinalizableReference.class. */ private static final String FINALIZABLE_REFERENCE = "com.google.common.base.FinalizableReference"; /** * Starts the Finalizer thread. FinalizableReferenceQueue calls this method reflectively. * 启动Finalizer线程,FinalizableReferenceQueue使用反射调用这个方法 * * @param finalizableReferenceClass FinalizableReference.class * @param frq reference to instance of FinalizableReferenceQueue that started this thread * @return ReferenceQueue which Finalizer will poll */ public static ReferenceQueue startFinalizer(Class
finalizableReferenceClass, Object frq) { /* * We use FinalizableReference.class for two things: 1) To invoke FinalizableReference.finalizeReferent() 2) To * detect when FinalizableReference's class loader has to be garbage collected, at which point, Finalizer can * stop running * * 我们使用FinalizableReference.class做两件事情 * 1) 调用FinalizableReference.finalizeReferent() * 2) 检测FinalizableReference的class loader是否会被垃圾回收,此时Finalizer将会停止运行 */ if (!finalizableReferenceClass.getName().equals(FINALIZABLE_REFERENCE)) { throw new IllegalArgumentException("Expected " + FINALIZABLE_REFERENCE + "."); } // 启动一个Finalizer后台线程 Finalizer finalizer = new Finalizer(finalizableReferenceClass, frq); Thread thread = new Thread(finalizer); thread.setName(Finalizer.class.getName()); thread.setDaemon(true); try { if (inheritableThreadLocals != null) { // 将thread的inheritableThreadLocals设为null inheritableThreadLocals.set(thread, null); } } catch (Throwable t) { logger.log(Level.INFO, "Failed to clear thread local values inherited" + " by reference finalizer thread.", t); } thread.start(); return finalizer.queue; } /** FinalizableReference的class的弱引用 */ private final WeakReference
> finalizableReferenceClassReference; /** FinalizableReferenceQueue的虚引用 */ private final PhantomReference
frqReference; /** ReferenceQueue */ private final ReferenceQueue queue = new ReferenceQueue(); private static final Field inheritableThreadLocals = getInheritableThreadLocalsField(); /** Constructs a new finalizer thread. */ private Finalizer(Class
finalizableReferenceClass, Object frq) { this.finalizableReferenceClassReference = new WeakReference
>(finalizableReferenceClass); // Keep track of the FRQ that started us so we know when to stop. this.frqReference = new PhantomReference
(frq, queue); } /** * Loops continuously, pulling references off the queue and cleaning them up. * * 不断循环并将queue里的reference出队做清理 */ @SuppressWarnings("InfiniteLoopStatement") @Override public void run() { try { while (true) { try { // remove()方法是一个死循环方法,直到返回Reference才会退出循环 cleanUp(queue.remove()); } catch (InterruptedException e) { /* ignore */ } } } catch (ShutDown shutDown) { /* ignore */ } } /** * Cleans up a single reference. Catches and logs all throwables. * * 清理一个reference */ private void cleanUp(Reference
reference) throws ShutDown { // 获取 finalizeReferent() 方法 Method finalizeReferentMethod = getFinalizeReferentMethod(); do { /* * This is for the benefit of phantom references. Weak and soft references will have already been cleared by * this point. * * 给虚引用使用的方法,如果是弱引用和软引用此时已经被cleared了 */ // 将Reference内的referent清除 reference.clear(); if (reference == frqReference) { /* * The client no longer has a reference to the FinalizableReferenceQueue. We can stop. * * 当FinalizableReferenceQueue的reference自己被加入到了ReferenceQueue中时,停止Finalizer */ throw new ShutDown(); } try { // 调用终结referent的方法 finalizeReferentMethod.invoke(reference); } catch (Throwable t) { logger.log(Level.SEVERE, "Error cleaning up after reference.", t); } /* * Loop as long as we have references available so as not to waste CPU looking up the Method over and over * again. * * 只要queue里还有reference就持续循环 */ // poll()是一个无延迟方法,如果queue里没有对象,则直接返回null,这点与remove()不同 } while ((reference = queue.poll()) != null); } /** * Looks up FinalizableReference.finalizeReferent() method. */ private Method getFinalizeReferentMethod() throws ShutDown { // 通过class的引用获取class Class
finalizableReferenceClass = finalizableReferenceClassReference.get(); if (finalizableReferenceClass == null) { /* * FinalizableReference's class loader was reclaimed. While there's a chance that other finalizable * references could be enqueued subsequently (at which point the class loader would be resurrected by virtue * of us having a strong reference to it), we should pretty much just shut down and make sure we don't keep * it alive any longer than necessary. */ throw new ShutDown(); } try { return finalizableReferenceClass.getMethod("finalizeReferent"); } catch (NoSuchMethodException e) { throw new AssertionError(e); } } public static Field getInheritableThreadLocalsField() { try { Field inheritableThreadLocals = Thread.class.getDeclaredField("inheritableThreadLocals"); inheritableThreadLocals.setAccessible(true); return inheritableThreadLocals; } catch (Throwable t) { logger.log(Level.INFO, "Couldn't access Thread.inheritableThreadLocals." + " Reference finalizer threads will inherit thread local" + " values."); return null; } } /** Indicates that it's time to shut down the Finalizer. */ @SuppressWarnings("serial") // Never serialized or thrown out of this class. private static class ShutDown extends Exception { }}

 

转载地址:http://rebra.baihongyu.com/

你可能感兴趣的文章
Python中变量的命名与使用(个人总结)
查看>>
【风马一族_SQL Server】
查看>>
python APScheduler定时任务框架
查看>>
lvs nginx HAProxy优缺点
查看>>
Laravel之认证服务
查看>>
性能测试总结(三)--工具选型篇
查看>>
免费好用的 Apple 工具(Windows 适用)
查看>>
水利行业传感器
查看>>
服务器做网页的搭建
查看>>
linux上部署ant
查看>>
arc073 F many moves(dp + 线段树)
查看>>
HT For Web 拓扑图背景设置
查看>>
长理 校赛的 一个贪心题
查看>>
vuecli3初尝试(转载)
查看>>
学习笔记:索引碎片、计划缓存、统计信息
查看>>
TSQL技巧(一) -- 子查询(subquery)
查看>>
espcms简约版的表单,提示页,搜索列表页
查看>>
KindEditor
查看>>
航拍去浆
查看>>
Linux-shell 练习题(一)
查看>>