Java 为什么要避免使用finalizer和Cleaner

 更新时间:2021年03月29日 11:41:23   作者:MR_程序猿刘  
这篇文章主要介绍了Java 为什么要避免使用finalizer和Cleaner,帮助大家更好的理解和学习使用Java,感兴趣的朋友可以了解下

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

避免使用的原因:

行为的不稳定性

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

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

移植性问题

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

性能问题

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

安全问题

  • 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

两个用处:

安全网

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

这是FileOutputStream的源码

回收本地对等体对象

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

以上就是Java 为什么要避免使用finalizer和Cleaner的详细内容,更多关于Java 避免使用finalizer和Cleaner的资料请关注脚本之家其它相关文章!

相关文章

  • Spring Cloud Feign简单使用详解

    Spring Cloud Feign简单使用详解

    本篇文章主要介绍了Spring Cloud Feign简单使用详解,小编觉得挺不错的,现在分享给大家,也给大家做个参考。一起跟随小编过来看看吧
    2018-02-02
  • Spring-webflux访问关系型数据库实战

    Spring-webflux访问关系型数据库实战

    这篇文章主要为大家介绍了Spring-webflux访问关系型数据库实战详解,有需要的朋友可以借鉴参考下,希望能够有所帮助,祝大家多多进步,早日升职加薪
    2023-07-07
  • 在JAR文件中找不到主清单属性的原因与解决方案

    在JAR文件中找不到主清单属性的原因与解决方案

    在Java中,一个JAR文件通常包含一个名为MANIFEST.MF的清单文件,这个文件定义了关于JAR文件的各种元数据,然而,有时我们可能会遇到一个问题,那就是在JAR文件中找不到主清单属性,本文给大家介绍了JAR文件中找不到主清单属性的原因和解决方案,需要的朋友可以参考下
    2024-04-04
  • mybatis中resulthandler的用法

    mybatis中resulthandler的用法

    这篇文章主要介绍了mybatis中resulthandler的用法,具有很好的参考价值,希望对大家有所帮助。如有错误或未考虑完全的地方,望不吝赐教
    2022-01-01
  • 使用Spring Boot实现操作数据库的接口的过程

    使用Spring Boot实现操作数据库的接口的过程

    本文给大家分享使用Spring Boot实现操作数据库的接口的过程,包括springboot原理解析及实例代码详解,感兴趣的朋友跟随小编一起看看吧
    2021-07-07
  • Jmeter分布式压力测试实现过程详解

    Jmeter分布式压力测试实现过程详解

    这篇文章主要介绍了Jmeter分布式压力测试实现过程详解,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的朋友可以参考下
    2020-09-09
  • 云IDE:Eclipse Che:Eclipse下一代IDE(推荐)

    云IDE:Eclipse Che:Eclipse下一代IDE(推荐)

    这篇文章主要介绍了云IDE:Eclipse Che:Eclipse下一代IDE,本文给大家介绍的非常详细,对大家的学习或工作具有一定的参考借鉴价值,需要的朋友可以参考下
    2020-09-09
  • Java设计模式中的抽象工厂模式解读

    Java设计模式中的抽象工厂模式解读

    这篇文章主要介绍了Java设计模式中的抽象工厂模式解读,抽象工厂模式为创建一组相关或相互依赖的对象提供一个接口,而且无需指定他们的具体类,需要的朋友可以参考下
    2023-11-11
  • Java日常练习题,每天进步一点点(16)

    Java日常练习题,每天进步一点点(16)

    下面小编就为大家带来一篇Java基础的几道练习题(分享)。小编觉得挺不错的,现在就分享给大家,也给大家做个参考。一起跟随小编过来看看吧,希望可以帮到你
    2021-07-07
  • Java中List转Map的几种常见方式与对比

    Java中List转Map的几种常见方式与对比

    JavaList转Map是一个非常常用的技术,对于Java开发人员来讲,掌握该技术可以帮助我们更加高效地操作List集合中的对象,这篇文章主要给大家介绍了关于Java中List转Map的几种常见方式与对比的相关资料,需要的朋友可以参考下
    2024-02-02

最新评论