这篇文章主要介绍了Java避免使用终结器和清洁的原因是什么,具有一定借鉴价值,感兴趣的朋友可以参考下,希望大家阅读完这篇文章之后大有收获、下面让小编带着大家一起了解一下。
java9之终结器前,java9使用清洁代替了终结器。相比终结器,清洁(它存在于一个独立类清洁剂中,需要时候注入到对应类中即可)不会污染API而且清洁有类库可以控制它的线程(它两都在后台线程中执行)。
避免使用的原因:
行为的不稳定性
它两都不能保证及时的执行,从方法可达到(对象被置空了)开始到最终的执行,时间是任意长的。所以千万不要使用他们来更新重要的持久状态,如释放流资源,分布式锁等。
system . gc和System.runFinalization这两个方法会增加终结器和清洁被执行的机会,但是不保证一定会执行。唯一能保证它两会被执行的两个方法(System.runFinalizersOnExit和Runtime.runFinalizersOnExit)有致命的缺陷,已经被废除很久了。
移植性问题
不同的JVM堆垃圾回收的算法不同,如果程序依赖终结器或者清洁被执行的时间点,那么程序的表现可能截然不同
性能问题
终结器和清洁有一个非常严重的性能损耗。
安全问题
- <李>
终结器中如果出现异常会导致线程终止,但是不会打印线程轨迹甚至警告都不会打印出来,而且使正在销毁的对象处于破坏状态,另一个线程如果使用这个破坏状态的对象会出现行为的不确定性.cleaner没有这个问题。
李> <李>终结器攻击:利于终结器方法,构建出恶意子类对象,非法调用父类方法.final类不会被构建恶意子类,所以不会遭到终结器攻击。对于非最终类,重写一个空的终结器方法并最终用修饰来防止终结器攻击。
李>//构建对象使用后不能再次被实例化 {public class 演示 private 才能boolean flag =,真的;//才能防止实例化 public 才能;演示(),{ ,,,if (国旗){ ,,,,,throw new RuntimeException(“不准许再次创建对象“); ,,,} ,,} public 才能;void 说(),{ ,,,System.out.println (“DemoUtils.say"); ,,} }//构建非法子类 {class Demo2  extends 演示 public 才能;以及接下来(){}//才能构建终结器攻击 @Override才能 protected 才能;void  finalize (), throws Throwable { ,,,//会调用父类方法 ,,,this.say (); ,,,system . exit (0); ,,} public 才能;static  void main (String [], args), throws InterruptedException { ,,,try { ,,,,,//创建子类对象必然会调用父类构造,所以会发生异常 ,,,,,//但是在gc中还是执行了父类的方法 ,,,,,Demo Demo =, new 以及接下来(); ,,,,,demo.say (); ,,,},catch (Exception e), { ,,,,,System.out.println (e); ,,,} ,,,system . gc (); ,,,//给垃圾回收提供时间 ,,,thread . sleep (5000); ,,} }//运行结果 java.lang.RuntimeException:不准许再次创建对象 DemoUtils。说
两个用处:
安全网
当资源的所有者忘记使用近方法的时候,终结器和清洁可以充当安全网,虽然不能保证及时的释放资源,但是迟一点释放总比永远不释放要好。要使用这样的安全网就要认证的考虑清除是否值得付出这样的代价。所以Java一些AutoCloseable实现中都添加了安全网。
这是FileOutputStream的源码
回收本地对等体对象
本地对等体:Java操作原生方法其实是委托给一个本地对等体对象,使用完成后Java对象会被GC回收,但是这个对等体对象不是Java对象不会被GC会回收。如果这个对象性能可以接受,而且没有需要及时释放的资源那么就可以使用终结器或者清洁进行回收了。但是如果这个对等体性能无法接受且拥有必须被及时终止的资源,那么就需要提供一个亲密的方法了。
感谢你能够认真阅读完这篇文章,希望小编分享的“Java避免使用终结器和清洁的原因是什么”这篇文章对大家有帮助,同时也希望大家多多支持,关注行业资讯频道,更多相关知识等着你来学习!