`

Finalizer Guardian Idiom

阅读更多

Effective Java 2nd 中Item 7: Avoid finalizers關於Finalizer Guardian Idiom的論述:

 

    If a subclass implementor overrides a superclass finalizer but forgets to invoke
it, the superclass finalizer will never be invoked. It is possible to defend against
such a careless or malicious subclass at the cost of creating an additional object
for every object to be finalized. Instead of putting the finalizer on the class
requiring finalization, put the finalizer on an anonymous class (Item 22) whose
sole purpose is to finalize its enclosing instance. A single instance of the
anonymous class, called a finalizer guardian, is created for each instance of the
enclosing class. The enclosing instance stores the sole reference to its finalizer
guardian in a private instance field so the finalizer guardian becomes eligible for
finalization at the same time as the enclosing instance. When the guardian is
finalized, it performs the finalization activity desired for the enclosing instance,
just as if its finalizer were a method on the enclosing class:

 

// Finalizer Guardian idiom
public class Foo {
    // Sole purpose of this object is to finalize outer Foo object
    private final Object finalizerGuardian = new Object() {
        @Override 
        protected void finalize() throws Throwable {
            ... // Finalize outer Foo object
        }
    };
    ... // Remainder omitted
}

 

Finalizer Guardian idiom是爲了防止該類被繼承且被覆蓋了finalize方法,並且沒有調用super.finalize()的情形(就是沒有使用所謂的finalizer chaining)。

因為在回收時去調Foo instance的finalize()會動態綁定到它子類的覆蓋方法上去,Foo的成員變量finalizerGuardian也會被回收,因此它的finalize()也會被調用,但是在這裡如果finalize了Foo的實例,finalizerGuardian自己怎麼辦?什麽都不寫,它會隱式回收自己嗎?我猜應該是會的,但不知道是怎麼實現的,因為覆蓋后相當於有關回收自己的代碼神馬都沒寫。

 

知道了,本身Object的finalize方法就是一個空方法,garbage collector無需任何多餘指示,只要一個空方法就可以進行回收了,被子類覆蓋后,新增的實現不影響原本對自己的回收。

 

2012.07.30 新增修改:

finalizerGuardian的回收機制如何被觸發?子類如果沒有finalizer chaining父类,那它只會finalize自己。

現在雖然沒有確鑿的資料證明,但這裡大膽結論:

當實例失去引用后即將被回收,它的成員變量也會先其而被回收,通過finalizerGuardian來finalize Foo對象,Foo對象只要被回收,它的成員自然而然就被強制回收。

 

// Manual finalizer chaining
@Override protected void finalize() throws Throwable {
    try {
        ... // Finalize subclass state
    } finally {
        super.finalize();
    }
}

 

但這樣不禁又帶來一個疑問,父類對象被finalize之後,子類對象會不會被連帶finalize?

1. 父類對象被finalize之後,子類對象如果也會被finalize,這樣的話,finalizer chaining又有何意義呢?也就是說子類去覆蓋父類的finalize方法有何意義呢?

2. 如果父類對象被finalize之後,子類對象不會被finalize,那麼manual finalizer chaining就有意義了,它用finalize方法來finalize subclass state。

 

所以正確結論看來是2。

 

最終結論:

1. 當存在finalizer chaining時,父類對象失去引用需要被回收,garbage collector回收其成員,然後欲調用父類對象finalize方法,沒有,動態綁定去調用子類對象finalize方法,在try塊中finalize自身,在finally塊中連鎖調用super.finalize()方法,因此父類對象及其無被引用成員也被回收。

2. 當不存在finalizer chaining時,父類對象失去引用需要被回收,garbage collector欲調用父類對象finalize方法,沒有,動態綁定去調用子類對象finalize方法,在try塊中finalize自身,在 finally塊中沒有連鎖調用super.finalize()方法,但garbage collector會去回收父類成員(why?當父類對象不被引用時,其成員就有機會被GC,意思是成員也真正失去引用了),當涉及到finalizerGuardian時,調用其finalize方法,其中再調用了父類對象的finalize方法,因此父類對象被回收,失去引用的成員連帶也被回收。

 

此二結論還需要進一步被論證。

 

 

 

 

 

 

分享到:
评论

相关推荐

    .NET 常见问答:完成器(Finalizer)、程序集名、方法信息等等

    在我的类中何时需要实现一个完成器?我是否一定要实现完成器,或者只是在我控制着 非托管资源时才需要实现它?我是否一定要在我的完成器中实现 IDisposable 接口?...关键字:finalizer,assembly names,methodinfo

    teclast-f5-ubuntu-finalizer:当前的HWSW KernelSystemACPI修改,以获取$ 400的Dream Ubuntu Linux笔记本电脑

    teclast-f5-ubuntu-finalizer:当前的HWSW KernelSystemACPI修改,以获取$ 400的Dream Ubuntu Linux笔记本电脑

    flexipatch-finalizer:自定义预处理器,用于从flexipatch版本中删除未选择的补丁,从而保留最终的补丁版本

    flexipatch-finalizer是一个自定义预处理器,它使用相同的配置文件,并剥离所有未使用代码的flexipatch构建,从而保留应用了选定补丁的软件构建。 该终结器的示例flexipatch构建可用于: :warning: 请务必注意,...

    finalizers:愚蠢的终结者

    愚蠢的终结者建造go build 跑# List all objects blocked by a finalizer./finalizers# List all objects with finalizers./finalizers --all例子./finalizersNAMESPACE NAME APIVERSION KIND FINALIZERSp-nf5gh ...

    java.lang.ref 简要一览

    NULL 博文链接:https://chong-zh.iteye.com/blog/1603616

    C#析构函数

    析构函数 finalizer destructor 整理的关于析构函数的描述以及介绍

    免费wordpress采集工具.zip

    wordpress免费采集和批量发布工具,该工具是147免费采集流出版本,支持wp等多CMS采集,以及支持多关键词批量采集多新闻源,可以做到同时批量采集并批量伪原创然后批量定时发布。

    免费迅睿CMS采集工具.zip

    迅睿免费采集和批量发布工具,该工具是147免费采集流出版本,支持迅睿等多CMS采集,以及支持多关键词批量采集多新闻源,可以做到同时批量采集并批量伪原创然后批量定时发布。

    dirty_scheduler:R17.3 +的Erlang脏调度程序示例

    dirty_scheduler 不要忘记使用“ --enable-dirty-schedulers”... 从Erlang 17.03开始,enif_schedule_dirty_nif,enif_schedule_dirty_nif_finalizer和enif_dirty_nif_finalizer被删除(erl_nif.h)。 更多信息: :

    基于.NET程序默认启动线程数讲解

    调试器帮助线程3.Finalizer线程 代码如下:class Program { static void Main(string[] args) { Console.WriteLine(“Main thread: {0}”, Thread.CurrentThread.ManagedThreadId); Console.ReadKey(); } } ...

    Go 语言编程 + Go 学习笔记

    Go 语言编程 + Go 学习笔记, ...6. Finalizer 第三部分 附录 A. 具 1. 具集 2. 条件编译 3. 跨平台编译 4. 预处理 B. 调试 1. GDB 2. Data Race C. 测试 1. Test 2. Benchmark 3. Example 4. Cover 5. PProf

    Android开发规范

    9.8 不要使用FINALIZER 29 9.9 使用完全限定IMPORT 29 9.10 对IMPORT语句排序 30 9.11 限制变量的作用范围 31 9.12 使用标准的JAVA ANNOTATION 32 9.13 简称等同于单词 32 9.14 使用TODO注释 33 9.15 慎用LOG 33 10 ...

    Linux 中awk 提取包含某个关键字的段落

    Finalizer #3 daemon prio=8 os_prio=0 tid=0x00007fb2dc1aa800 nid=0x63f6 in Object.wait() [0x00007fb2be61f000] java.lang.Thread.State: WAITING (on object monitor) at java.lang.Object.wait(Native ...

    gradle-circle样式::rocket::rocket::rocket:移至基线

    Gradle圈样式Gradle插件可总结失败的Gradle构建,和失败进行特殊处理。快速开始将以下内容添加到项目的... 然后,它会自动为Checkstyle和FindBugs插件启用XML输出,并添加一个finalizer任务,以使用CircleCI期望的JUni

    feinerleiser:Feinerleiser 为 jabref 实施人文学科的引用规则-开源

    Feinerleiser (speak finalizer) 获取一个 odt 文件,其中包含由 jabref 插入的引文,并根据用户在 xml 文件中设置的规则对其进行扩展。 与工程、心理学或医学中使用的引用风格相反 [Doe 1985; 123] 用户可以创建...

    使用mimalloc的简单保守GC-C/C++开发

    migc小型简单的库,使用mimalloc API实现保守的GC。...有:migc_add_roots和migc_delete_roots用于添加或删除指针范围以扫描潜在的指针,migc_register_finalizer用于在死对象上调用终结器。 快速分配。 什么时候

    Go学习笔记(第四版).zip

    6. Finalizer 241 第三部分 附录 249 A. ⼯具 250 1. ⼯具集 250 2. 条件编译 251 3. 跨平台编译 253 4. 预处理 254 6 Go 学习笔记, 第 4 版 B. 调试 255 1. GDB 255 2. Data Race 255 C. 测试 258 1. Test 258 2. ...

    go学习笔记

    6. Finalizer 241 第三部分 附录 249 A. ⼯工具 250 1. ⼯工具集 250 2. 条件编译 251 3. 跨平台编译 253 4. 预处理 254 Go 学习笔记, 第 4 版 6 B. 调试 255 1. GDB 255 2. Data Race 255 C. 测试 258 1. Test 258 ...

    关于finalize机制和引用、引用队列的用法详解

    C++有析构函数这个东西,能够很好地在对象销毁前...JVM启动的时候,会创建一个Finalizer线程来支持finalize方法的执行。 关于引用和引用队列,java提供了4种引用类型,在垃圾回收的时候,都有自己各自的独特表现。Refe

Global site tag (gtag.js) - Google Analytics