Java9以后的垃圾回收


1: finalize() 方法

  • finallize() 方法是Object類的方法, 用於在類被GC回收時 做一些處理操作, 但是JVM並不能保證finalize(0 ) 方法一定被執行,
  • 由於finalize()方法的調用時機具有不確定性,從一個對象變得不可到達開始,到finalize()方法被執行,所花費的時間這段時間是任意長的。我們並不能依賴finalize()方法能及時的回收占用的資源,可能出現的情況是在我們耗盡資源之前,gc卻仍未觸發,因而通常的做法是提供顯示的close()方法供客戶端手動調用
  • 所以一般不建議使用finalize 方法, JDK9 開始已久被廢除

- 總結缺點

 1: finalize機制本身就是存在問題的。

  2:finalize機制可能會導致性能問題,死鎖和線程掛起。

 3:finalize中的錯誤可能導致內存泄漏;如果不在需要時,也沒有辦法取消垃圾回收;並且沒有指定不同執行finalize對象的執行順序。此外,沒有辦法保證finlize的執行時間。
遇到這些情況,對象調用finalize方法只有被無限期延后

- 觀察finalize方法延長類生命周期

class User{
	
	public static User user = null;

	@Override
	protected void finalize() throws Throwable {
		System.out.println("User-->finalize()");
		user = this;
	}
	
}

public class FinalizerTest {
	public static void main(String[] args) throws InterruptedException {
		User user = new User();
		user = null;
		System.gc();
		Thread.sleep(1000);
		
		user = User.user;
		System.out.println(user != null);//true
		
		user = null;
		System.gc();
		Thread.sleep(1000);
		System.out.println(user != null);//false
	}
}

  

- JDk9 以前的垃圾回收代碼

public class Finalizer {

    @Override
    protected void finalize() throws Throwable {
        System.out.println("Finalizer-->finalize()");
    }

    public static void main(String[] args) {
        Finalizer f = new Finalizer();
        f = null;
        
        System.gc();//手動請求gc
    }
}
//輸出 Finalizer-->finalize()

 

2:Cleaner類的使用

簡介:

 在Java9 以后 提供了最終類Clear來代替實現,下面看一下官方例子

package Thread;

import java.lang.ref.Cleaner;

public class CleaningExample implements AutoCloseable{

    
    private final static Cleaner CLEANER=Cleaner.create();// 創建者模式創建對象
    
   static  class State implements Runnable{ // 清理對象 下面說
        State() {
            System.out.println("init");
        }
        @Override
        public void run() {
            System.out.println("close");
        }
    }
    
    private final State state;
    private final Cleaner.Cleanable   cleanable; // clearner 中的接口 實現唯一的清理方法
    
    public CleaningExample() {
        super();
        this.state = new State();
        this.cleanable=CLEANER.register(this, state); // 注冊清理容器中 並且需要清理對象的引用
    }

    @Override
    public void close() throws Exception {
        cleanable.clean(); //進行清理操作
    }
    
    public static void main(String[] args) {
        while(true) {
            new CleaningExample();
        }
    }

}

 

上面 看出:

 

  • Cleaner 是最終類 不能被重寫, 內部方法基本以靜態方法提供  掌握例子上面的方法即可

 重點指出

 static class State implements Runnable
  •  如果直接在類中直接定義實現, 必須提供一個靜態內部類 (強制),否者不能進行回收   原因(: 普通內部類 局部內部類 對於外部類有依賴(引用),無法真正實現內存的釋放 )
  •   可以選擇直接定義外部類 (較為復雜,需要傳遞清理引用  Cleanable)

什么時候被回收?

  • * 1. 注冊的Object處於幻象引用狀態

  • * 2. 顯式調用 clean 方法

實際例子(模版)

public class CleaningExample extends Thread implements AutoCloseable {
    private final static Cleaner CLEANER = Cleaner.create();
    private final State state;
    private final Cleaner.Cleanable cleanable;
    
    public CleaningExample() {
        this.state = new State();
        this.cleanable = CLEANER.register(this, state);
    }

    @Override
    public void close() throws Exception {
        cleanable.clean();
    }
    
    @SuppressWarnings("resource")
    public static void main(String[] args) {
        while (true) {
            CleaningExample example = new CleaningExample();
        }
    }
    // 模擬業務請求
    @Override
    public void run() {
        System.out.println("數據庫 海量 查詢請求 ................");
    }
    // 清理模版
    class State implements Runnable {
        State() {
            System.out.println("<--- init --->");
        }
        @Override
        public void run() {
            System.out.println("<--- close --->");
        }
    }
}

 

實現基礎

    /**
     * Heads of a CleanableList for each reference type.
     */
    final PhantomCleanable<?> phantomCleanableList;

    final WeakCleanable<?> weakCleanableList;

    final SoftCleanable<?> softCleanableList;

    // The ReferenceQueue of pending cleaning actions
    final ReferenceQueue<Object> queue;

 

在CleanerImpl 類進行clearner類的最終實現,看以看到定義的這些個字段,基本上明確了 他的基本原理

 

 

 

 

 


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM