Java 為什么要避免使用finalizer和Cleaner
java9之前finalizer,java9使用cleaner代替了finalizer。相比finalizer,cleaner(它存在于一個獨立類Cleaner中,需要時候注入到對應類中即可)不會污染API而且cleaner有類庫可以控制它的線程(它兩都在后臺線程中執(zhí)行)。
避免使用的原因:
行為的不穩(wěn)定性
它兩都不能保證及時的執(zhí)行,從方法可達到(對象被置空了)開始到最終的執(zhí)行,時間是任意長的。所以千萬不要使用他們來更新重要的持久狀態(tài),如釋放流資源、分布式鎖等。
System.gc和System.runFinalization這兩個方法會增加finalizer和cleaner被執(zhí)行的機會,但是不保證一定會執(zhí)行。唯一能保證它兩會被執(zhí)行的兩個方法(System.runFinalizersOnExit和Runtime.runFinalizersOnExit)有致命的缺陷,已經(jīng)被廢除很久了。
移植性問題
不同的JVM堆垃圾回收的算法不同,如果程序依賴finalizer或者cleaner被執(zhí)行的時間點,那么程序的表現(xiàn)可能截然不同
性能問題
finalizer和cleaner有一個非常嚴重的性能損耗。
安全問題
- finalizer中如果出現(xiàn)異常會導致線程終止,但是不會打印線程軌跡甚至警告都不會打印出來,而且使正在銷毀的對象處于破壞狀態(tài),另一個線程如果使用這個破壞狀態(tài)的對象會出現(xiàn)行為的不確定性。cleaner沒有這個問題。
- finalizer攻擊:利于finalizer方法,構建出惡意子類對象,非法調用父類方法。final類不會被構建惡意子類,所以不會遭到finalizer攻擊。對于非final類,重寫一個空的finalizer方法并用final修飾來防止finalizer攻擊。
//構建對象使用后不能再次被實例化
public class Demo{
private boolean flag = true;
//防止實例化
public Demo() {
if (flag){
throw new RuntimeException("不準許再次創(chuàng)建對象");
}
}
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 {
//創(chuàng)建子類對象必然會調用父類構造,所以會發(fā)生異常
//但是在gc中還是執(zhí)行了父類的方法
Demo demo = new Demo2();
demo.say();
} catch (Exception e) {
System.out.println(e);
}
System.gc();
//給垃圾回收提供時間
Thread.sleep(5000);
}
}
//運行結果
java.lang.RuntimeException: 不準許再次創(chuàng)建對象
DemoUtils.say
兩個用處:
安全網(wǎng)
當資源的所有者忘記使用close方法的時候,finalizer和cleaner可以充當安全網(wǎng),雖然不能保證及時的釋放資源,但是遲一點釋放總比永遠不釋放要好。要使用這樣的安全網(wǎng)就要認證的考慮清除是否值得付出這樣的代價。所以Java一些AutoCloseable實現(xiàn)中都添加了安全網(wǎng)。
這是FileOutputStream的源碼

回收本地對等體對象
本地對等體:java操作native方法其實是委托給一個本地對等體對象,使用完成后java對象會被GC回收,但是這個對等體對象不是java對象不會被會GC回收。如果這個對象性能可以接受,而且沒有需要及時釋放的資源那么就可以使用finalizer或者cleaner進行回收了。但是如果這個對等體性能無法接受且擁有必須被及時終止的資源,那么就需要提供一個close方法了。
以上就是Java 為什么要避免使用finalizer和Cleaner的詳細內容,更多關于Java 避免使用finalizer和Cleaner的資料請關注腳本之家其它相關文章!
相關文章
Spring-webflux訪問關系型數(shù)據(jù)庫實戰(zhàn)
這篇文章主要為大家介紹了Spring-webflux訪問關系型數(shù)據(jù)庫實戰(zhàn)詳解,有需要的朋友可以借鑒參考下,希望能夠有所幫助,祝大家多多進步,早日升職加薪2023-07-07
使用Spring Boot實現(xiàn)操作數(shù)據(jù)庫的接口的過程
本文給大家分享使用Spring Boot實現(xiàn)操作數(shù)據(jù)庫的接口的過程,包括springboot原理解析及實例代碼詳解,感興趣的朋友跟隨小編一起看看吧2021-07-07
云IDE:Eclipse Che:Eclipse下一代IDE(推薦)
這篇文章主要介紹了云IDE:Eclipse Che:Eclipse下一代IDE,本文給大家介紹的非常詳細,對大家的學習或工作具有一定的參考借鑒價值,需要的朋友可以參考下2020-09-09

