java9之前finalizer,java9使用cleaner代替了finalizer。相比finalizer,cleaner(它存在于一个独立类Cleaner中,需要时候注入到对应类中即可)不会污染API而且cleaner有类库可以控制它的线程(它两都在后台线程中执行)。

避免使用的原因:

  1. 行为的不稳定性

    • 它两都不能保证及时的执行,从方法可达到(对象被置空了)开始到最终的执行,时间是任意长的。所以千万不要使用他们来更新重要的持久状态,如释放流资源、分布式锁等。

    • System.gc和System.runFinalization这两个方法会增加finalizer和cleaner被执行的机会,但是不保证一定会执行。唯一能保证它两会被执行的两个方法(System.runFinalizersOnExit和Runtime.runFinalizersOnExit)有致命的缺陷,已经被废除很久了。

  1. 移植性问题

    不同的JVM堆垃圾回收的算法不同,如果程序依赖finalizer或者cleaner被执行的时间点,那么程序的表现可能截然不同

  2. 性能问题

    finalizer和cleaner有一个非常严重的性能损耗。

  3. 安全问题

    • finalizer中如果出现异常会导致线程终止,但是不会打印线程轨迹甚至警告都不会打印出来,而且使正在销毁的对象处于破坏状态,另一个线程如果使用这个破坏状态的对象会出现行为的不确定性。cleaner没有这个问题。

    • finalizer攻击:利于finalizer方法,构建出恶意子类对象,非法调用父类方法。final类不会被构建恶意子类,所以不会遭到finalizer攻击。对于非final类,重写一个空的finalizer方法并用final修饰来防止finalizer攻击。

      //构建对象使用后不能再次被实例化
      public class Demo{
         private boolean flag = true;
         //防止实例化
         public  Demo() {
             if (flag){
                 throw new RuntimeException("不准许再次创建对象");
            }
        }
         public  void say() {
             System.out.println("DemoUtils.say");
        }
      }
      //构建非法子类
      class Demo2 extends Demo{
         public Demo2(){}
         //构建finalizer攻击
         @Override
         protected void finalize() throws Throwable {
             //会调用父类方法
             this.say();
             System.exit(0);
        }
         public static void main(String[] args) throws InterruptedException {
             try {
                 //创建子类对象必然会调用父类构造,所以会发生异常
                 //但是在gc中还是执行了父类的方法
                 Demo demo = new Demo2();
                 demo.say();
            } catch (Exception e) {
                 System.out.println(e);
            }
             System.gc();
             //给垃圾回收提供时间
             Thread.sleep(5000);
        }
      }
      //运行结果
      java.lang.RuntimeException: 不准许再次创建对象
      DemoUtils.say

两个用处:

  1. 安全网

    当资源的所有者忘记使用close方法的时候,finalizer和cleaner可以充当安全网,虽然不能保证及时的释放资源,但是迟一点释放总比永远不释放要好。要使用这样的安全网就要认证的考虑清除是否值得付出这样的代价。所以Java一些AutoCloseable实现中都添加了安全网。

    这是FileOutputStream的源码

  2. 回收本地对等体对象

    本地对等体:java操作native方法其实是委托给一个本地对等体对象,使用完成后java对象会被GC回收,但是这个对等体对象不是java对象不会被会GC回收。如果这个对象性能可以接受,而且没有需要及时释放的资源那么就可以使用finalizer或者cleaner进行回收了。但是如果这个对等体性能无法接受且拥有必须被及时终止的资源,那么就需要提供一个close方法了。

effective解读-第八条 避免使用finalizer和Cleaner的更多相关文章

  1. Effective Java 第三版——8. 避免使用Finalizer和Cleaner机制

    Tips <Effective Java, Third Edition>一书英文版已经出版,这本书的第二版想必很多人都读过,号称Java四大名著之一,不过第二版2009年出版,到现在已经将 ...

  2. 《Effective Java》 读书笔记(八)避免使用Finalizer和Cleaner机制

    Finalizer和Cleaner并不等同于C++中的析构函数,是不确定多久会被调用的,甚至有时候可能不会被调用,因此除了作为一个安全网或者终止非关键的本地资源,不应该在Finalizer或Clean ...

  3. effective解读-第一条 静态工厂创建对象代替构造器

    好处 有名称,能见名知意.例如BigInteger的probablePrime方法 享元模式.单例模式中使用 享元模式:创建对象代价很高,重复调用已有对象,例如数据库连接等.享元模式是单例模式的一个拓 ...

  4. JDK源码分析(8)之 Reference 完全解读

    在阅读本文之前最好对 Reference 框架有一个整体的把握,可以参考我上一篇博客 Reference 框架概览 :本文主要讲了 Reference 的子类实现和应用(SoftReference,W ...

  5. 阅读《Effective Java》每条tips的理解和总结(1)

    <Effective Java>这本书的结构是90来条tips,有长有短,每条tip都值的学习.这里根据对书中每条tip的理解做简短的总结,方便日后回顾.持续更新~ 1. 考虑用静态方法代 ...

  6. Java 高效编程(Effective Java)中文第三版(补档)

    来源:sjsdfg/effective-java-3rd-chinese <Effective Java, Third Edition>一书英文版已经出版,这本书的第二版想必很多人都读过, ...

  7. 《Effective Java 第三版》目录汇总

    经过反复不断的拖延和坚持,所有条目已经翻译完成,供大家分享学习.时间有限,个别地方翻译得比较仓促,希望有疑虑的地方指出批评改正. 第一章简介 忽略 第二章 创建和销毁对象 1. 考虑使用静态工厂方法替 ...

  8. Effective.Java第1-11条

    1. 考虑使用静态工厂方法替代构造方法 一个类可以提供一个公共静态工厂方法,它只是返回类实例的静态方法.例如JDK的Boolean的valueOf方法: public final class Bool ...

  9. 《Effective Java》第1章 创建和销毁对象

    第1条 用静态工厂方法代替构造器 这个静态工厂,与设计模式中的静态工厂不同,这里的静态工厂方法,替换为“静态方法”比较好理解,主要就是建议编写静态方法来创建对象. 使用静态方法的好处: 1.静态方法有 ...

随机推荐

  1. How to build a sortable table in native js?

    How to build a sortable table in native/vanilla js? H5 DnD https://developer.mozilla.org/zh-CN/docs/ ...

  2. js add Struct to ArrayBuffer

    使用struct-buffer为ArrayBuffer添加结构体 $ npm i struct-buffer 1. 创建结构体 import { DWORD, string_t, StructBuff ...

  3. outlook & email & animation

    outlook & email & animation tada position div

  4. 两年Java,去字节跳动写Python和Go

    前言 2019年5月,在收到offer邮件的那一刻,我仍然不敢相信自己这一番际遇.经历了七场面试,终于得偿所望,拿到了字节跳动的offer. 做加入大厂的决定并不是巧合.在多年的职业生涯里,我曾多次对 ...

  5. HTTP 1.x 学习笔记 —— Web 性能权威指南

    HTTP 1.0的优化策略非常简单,就一句话:升级到HTTP 1.1.完了! 改进HTTP的性能是HTTP 1.1工作组的一个重要目标,后来这个版本也引入了大量增强性能的重要特性,其中一些大家比较熟知 ...

  6. 用铁电存储器FRAM让穿戴式设备更省电

    可穿戴设备应用中的显示屏消耗了大部分电池电力.解决方法之一是直接提高电池容量,但是大容量电池会加大尺寸和重量,对可穿戴设备不合适,尤其是在市场不断追求更小型化的新款产品时更是如此.更具挑战性的是电池技 ...

  7. Java中base64与byte[]转换

    1.base64转byte[] 导包: import java.util.Base64 转换: String base64Str = base64的字符串; byte[] bytes = Base64 ...

  8. SpringCloud之服务配置

    1.config 1.1定义 对于分布式微服务,有很多的配置,那么修改起来很麻烦.这就需要对这些配置文件进行集中式的管理,config的功能就是用来统一管理配置文件的.它为微服务提供集中化的外部配置支 ...

  9. oracle ora-01114 IO error writing block to file 207 (block # )

    oracle ORA-01114 IO error writing block to file 207 (block # ) Reference: https://stackoverflow.com/ ...

  10. Python2和Python3编码的区别

    Python2 python2中有两种储存变量的形式,第一种:Unicode:第二种:按照coding头来的. 假设python2用utf8存储x='中文',当你print(x)的时候,终端接收gbk ...