gpt4 book ai didi

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

转载 作者:qq735679552 更新时间:2022-09-29 22:32:09 25 4
gpt4 key购买 nike

CFSDN坚持开源创造价值,我们致力于搭建一个资源共享平台,让每一个IT人在这里找到属于你的精彩世界.

这篇CFSDN的博客文章Java 为什么要避免使用finalizer和Cleaner由作者收集整理,如果你对这篇文章有兴趣,记得点赞哟.

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攻击。
?
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
//构建对象使用后不能再次被实例化
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 为什么要避免使用finalizer和Cleaner

回收本地对等体对象

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

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

原文链接:https://www.cnblogs.com/chengxuyuan-liu/p/14591193.html 。

最后此篇关于Java 为什么要避免使用finalizer和Cleaner的文章就讲到这里了,如果你想了解更多关于Java 为什么要避免使用finalizer和Cleaner的内容请搜索CFSDN的文章或继续浏览相关文章,希望大家以后支持我的博客! 。

25 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com