簡體   English   中英

使用 java.lang.ref.Cleaner 替代 Object.finalize

[英]Usage of java.lang.ref.Cleaner as alternative to Object.finalize

我需要清理 JNI 調用分配的資源。 通過覆蓋Object.finalize()方法很容易做到這一點。 由於從 Java 9 開始不推薦使用此方法,因此我嘗試使用新的java.lang.ref.Cleaner類來實現相同的目的。

下面是在實例被垃圾回收之前調用ToBeCleaned.cleanUp方法的代碼:

import java.lang.ref.Cleaner;
import java.lang.ref.WeakReference;

public class ToBeCleaned {

    private static Cleaner cleaner = Cleaner.create();

    public ToBeCleaned() {
        cleaner.register(this, new CleanRunnable(this));
    }

    void cleanUp () {
        // do cleanup
    }


    static class CleanRunnable implements Runnable {
        // It has to be weak reference, otherwise ToBeCleaned instance
        // would never be eligible for GC
        private WeakReference<ToBeCleaned> toBeCleanedWeakReference;

        CleanRunnable(ToBeCleaned  toBeCleaned) {
            this.toBeCleanedWeakReference = new WeakReference<>(toBeCleaned);
        }

        @Override
        public void run() {
            toBeCleanedWeakReference.get().cleanUp();
        }
    }
}

我的問題:這是正確的方法嗎?

你的方法有缺陷。 “清理操作”不得依賴於對向Cleaner注冊的實例的訪問權限。

簡而言之,在您的代碼中對toBeCleanedWeakReference.get()的調用將返回null因為ToBeCleaned實例至少從我們的角度來看,到ToBeCleaned已經被垃圾收集了。

正確的方法是以某種方式引用需要清理的資源,而無需“通過” ToBeCleaned實例。 通常這意味着:

  1. 使清理操作和資源成為同一個對象(與使用Cleaner注冊的對象不同)。 Cleaner文檔展示了這種方法的一個例子。

  2. 在實例化它時,將對資源的引用(而不是向Cleaner注冊的對象)傳遞給清理操作。 下面是一個例子:

     public class ToBeCleaned implements AutoCloseable { // documentation suggests you should preferably have one // Cleaner instance per library private static final Cleaner CLEANER = ...; private final Cleaner.Cleanable cleanable; private final SomeResource resource; public ToBeCleaned() { resource = ...; cleanable = CLEANER.register(this, new CleaningAction(resource)); } @Override public void close() { cleanable.clean(); } private static class CleaningAction implements Runnable { private final SomeResource resource; CleaningAction(SomeResource resource) { this.resource = resource; } @Override public void run() { // clean up 'resource' } } }

這兩個示例都實現了AutoCloseable 這使您的 API 用戶能夠按需釋放資源,而不是等待垃圾收集器啟動(這使得Cleaner更像是“備份”)。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM