/*
* 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
*
* <p>
* 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反射地来访问他
*
* <p>
* 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
*
* <p>
* {@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<Object> 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<Class<?>> finalizableReferenceClassReference;
/** FinalizableReferenceQueue的虚引用 */
private final PhantomReference<Object> frqReference;
/** ReferenceQueue */
private final ReferenceQueue<Object> queue = new ReferenceQueue<Object>(); private static final Field inheritableThreadLocals = getInheritableThreadLocalsField(); /** Constructs a new finalizer thread. */
private Finalizer(Class<?> finalizableReferenceClass, Object frq) {
this.finalizableReferenceClassReference = new WeakReference<Class<?>>(finalizableReferenceClass); // Keep track of the FRQ that started us so we know when to stop.
this.frqReference = new PhantomReference<Object>(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 {
}
}

Guava Finalizer的更多相关文章

  1. Spring cache简单使用guava cache

    Spring cache简单使用 前言 spring有一套和各种缓存的集成方式.类似于sl4j,你可以选择log框架实现,也一样可以实现缓存实现,比如ehcache,guava cache. [TOC ...

  2. Guava库介绍之实用工具类

    作者:Jack47 转载请保留作者和原文出处 欢迎关注我的微信公众账号程序员杰克,两边的文章会同步,也可以添加我的RSS订阅源. 本文是我写的Google开源的Java编程库Guava系列之一,主要介 ...

  3. Google Java编程库Guava介绍

    本系列想介绍下Java下开源的优秀编程库--Guava[ˈgwɑːvə].它包含了Google在Java项目中使用一些核心库,包含集合(Collections),缓存(Caching),并发编程库(C ...

  4. [Java 缓存] Java Cache之 Guava Cache的简单应用.

    前言 今天第一次使用MarkDown的形式发博客. 准备记录一下自己对Guava Cache的认识及项目中的实际使用经验. 一: 什么是Guava Guava工程包含了若干被Google的 Java项 ...

  5. [转载]Google Guava官方教程(中文版)

      原文链接  译文链接 译者: 沈义扬,罗立树,何一昕,武祖  校对:方腾飞 引言 Guava工程包含了若干被Google的 Java项目广泛依赖 的核心库,例如:集合 [collections] ...

  6. java开发人员,最应该学习和熟练使用的工具类。google guava.(谷歌 瓜娃)

    学习参考文章: http://blog.csdn.net/wisgood/article/details/13297535 http://ifeve.com/google-guava/ http:// ...

  7. Guava学习笔记(一)概览

    Guava是谷歌开源的一套Java开发类库,以简洁的编程风格著称,提供了很多实用的工具类, 在之前的工作中应用过Collections API和Guava提供的Cache,不过对Guava没有一个系统 ...

  8. Guava monitor

    Guava的com.google.util.concurrent类库提供了相对于jdk java.util.concurrent包更加方便实用的并发类,Monitor类就是其中一个.Monitor类在 ...

  9. 使用Guava EventBus构建publish/subscribe系统

    Google的Guava类库提供了EventBus,用于提供一套组件内publish/subscribe的解决方案.事件总线EventBus,用于管理事件的注册和分发.在系统中,Subscribers ...

随机推荐

  1. Python3 kmeans 聚类算法

    # -*- coding: utf-8 -*- """ Created on Wed Jan 10 19:18:56 2018 @author: markli " ...

  2. Java 内存模型 ,一篇就够了!

    Java 虚拟机   我们都知道 Java 语言的可以跨平台的,这其中的核心是因为存在 Java 虚拟机这个玩意.虚拟机,顾名思义就是虚拟的机器,这不是真实存在的硬件,但是却可以和不同的底层平台进行交 ...

  3. Uncaught Error: Syntax error, unrecognized expression: [flag=]报错处理方法

    今早运行项目的时候报这个错误: 百度翻译的解释是:未命名错误:语法错误,未识别表达式:[FLAG= ]   也就是书写规范问题. 可是我查了对应的js: 字符串拼接没什么问题,经常这样写. 这时看报错 ...

  4. 区别ES3ES5和ES6this的指向问题。区分普通函数和箭头函数中this的指向问题

    ES3 ES5this的指向问题 this指的是该函数被调用的对象 var foo = function () { this.a = 'a', this.b = 'b', this.c = { a: ...

  5. Failed to connect socket to '/var/run/libvirt/libvirt-sock'的问题解决

    1.增加libvirtd用户组 groupadd libvirtd 2.设置用户到组 sudo usermod -a -G libvirtd $USER 3.设置启动libvirtd服务的用户组 vi ...

  6. Android中使用隐藏API(大量图解)

    Android SDK的很多API是隐藏的,我无法直接使用.但是我们通过编译Android系统源码可以得到完整的API. 编译Android系统源码后可以在out\target\common\obj\ ...

  7. SimpleUpdater.NET

    本类库+工具用于快速实现一个简单的自动更新程序,旨在快速简单地为现有的.Net应用程序添加上比较简单的自动更新功能. 本页包含以下内容 概述 整个自动升级工作的流程 更新包生成工具 发布更新包 为应用 ...

  8. Revit API创建几何实体Solid并找到与之相交的元素

    几何实体的创建方法之一:构成封闭底面,指定拉伸方向与拉伸高度.GeometryCreationUtilities ;         , pt.Y - dBoxLength / , pt.Z);    ...

  9. mysql大文本数据类型的使用需要考虑实际情况

    mysql数据类型简介(http://news.newhua.com/news1/program_database/2008/618/08618103911CD92HJ6CKI2I9I0AH5CGK1 ...

  10. 在ASP.NET MVC4中使用Quartz.NET执行定时任务

    本篇在ASP.NET MVC下实践使用Quartz.NET执行定时任务. 首先通过NuGet安装Quartz.NET. 使用Quartz.NET的大致思路是:1.实现IJob接口,定义具体要做的事情2 ...