Java Cleaner 类

java.lang.ref.Cleanerは Java 9 で導入されたツールで、オブジェクトのクリーンアップ作業を管理し、ガベージコレクション時にリソースをクリーンアップする安全な方法を提供します。これはfinalizefinalize() メソッドを置き換え、オブジェクトが使用されなくなったときにクリーンアップ操作を実行して外部リソースを解放し、finalizefinalize() より効率的で信頼性が高くなります。

1. Cleanerの役割

Cleanerクリーンアップアクション(clean-up action)を登録できます。このアクションは、オブジェクトが到達不能(つまり、まもなくガベージコレクションされる)になったときに自動的に実行されます。典型的な適用シナリオは次のとおりです。

  • 非 Java メモリリソースを自動的に解放します。例えば、ファイル、データベース接続、ソケット接続などを閉じます。
  • 置き換えfinalize、リソースの自動解放を実現し、呼び出し忘れによるclose()finalize() メソッドによるリソースリークを回避します。

2. Cleanerの基本的な使用方法

以下はCleanerCleaner の基本的な使い方:

  • 作成Cleanerインスタンス:Cleaner.create()。
  • クリーンアップが必要なオブジェクトを作成し、それをクリーンアップアクションと一緒にCleanerCleaner に登録します。このオブジェクトが参照されなくなると、クリーンアップアクションが自動的に実行されます。

3. 使用例

次の例は、CleanerCleaner を使用してクリーンアップが必要なリソースを作成し、オブジェクトが到達不能になったときにクリーンアップ操作を自動的に実行する方法を示しています:

例

import java.lang.ref.Cleaner;

public class CleanerExample {

    // Cleaner インスタンスを作成する
    private static final Cleaner cleaner = Cleaner.create();

    // クリーンアップが必要なリソースを定義する
    static class Resource implements AutoCloseable {
        // クリーンアップタスク - リソースを解放するため
        private final Cleaner.Cleanable cleanable;

        Resource() {
            // クリーンアップタスクを登録し、Resource インスタンスが到達不能になったときにクリーンアップアクションを実行する
            this.cleanable = cleaner.register(this, new ResourceCleaner());
            System.out.println("Resource initialized");
        }

        // リソースをクリーンアップする
        private static class ResourceCleaner implements Runnable {
            @Override
            public void run() {
                System.out.println("Cleaning up resource...");
            }
        }

        @Override
        public void close() {
            // 能動的にリソースを解放し、Cleaner に登録されたクリーンアップタスクをキャンセルする
            cleanable.clean();
            System.out.println("Resource closed");
        }
    }

    public static void main(String[] args) {
        // リソースを使用する
        try (Resource resource = new Resource()) {
            System.out.println("Using resource...");
        } // close() を自動的に呼び出し、手動でリソースをクリーンアップする

        // close() を呼び出さない場合、GC がクリーンアップタスクを実行する
        new Resource(); // close() を呼び出さず、GC によるクリーンアップのトリガーを待つ
        System.gc(); // GC の実行を促す(クリーンアップがすぐに実行されるとは限らない)
    }
}

4. コードの説明

  • Cleaner インスタンス:Cleaner.create()が作成され、Cleanerクリーンアップが必要なリソースを登録するために使用されます。
  • クリーンアップタスクの登録:Resourceクラス内で、呼び出し、cleaner.register(this, new ResourceCleaner())現在のオブジェクトを登録し、Cleanerクリーンアップタスクを指定します。ResourceCleaner。
  • 自動クリーンアップ:Resourceインスタンスが他に強い参照を持たず、まもなくガベージコレクションされるとき、Cleanerが自動的に呼び出し、ResourceCleaner.run()「Cleaning up resource...」と出力します。
  • 手動クリーンアップ:メソッドを通じてclose()能動的に呼び出し、cleanable.clean()、直ちにリソースをクリーンアップし、Cleanerのタスクをキャンセルします。

5. Cleaner の特徴と利点

  • 高効率:CleanerJVM によって管理されるため、finalizefinalize の低効率なパフォーマンス問題を回避します。
  • finalize の遅延を回避:Cleaner登録されたタスクは、オブジェクトが到達不能になった後にタイムリーに実行できます。ガベージコレクタの遅延呼び出しを待つ必要はありません。
  • 制御性:Cleaner能動的に呼び出し、clean()リソースをクリーンアップし、クリーンアップ後に自動的にタスクをキャンセルして、重複するクリーンアップを回避します。
  • メモリとリソースの安全性:手動によるリソース管理のリスクを減らし、システムリソースが正しく解放されることを保証します。

6. Cleaner の使用場面

Cleaner自動解放が必要なリソースの管理に適しています。特に、finalize をtry-with-resources使用できない場合に適しています。

  • Native リソース:非ヒープメモリリソースの管理に使用されます。例えば、DirectByteBuffer、JNI またはその他のローカルリソースです。
  • キャッシュクリーンアップ:オブジェクトがガベージコレクションされるとき、関連するキャッシュデータを自動的にクリーンアップします。
  • ノンブロッキングリソースクリーンアップ:ブロッキングのないリソースクリーンアップタスクに使用されます。例えば、他のサービスにオブジェクトが回収されたことを通知します。

7. 注意事項

  • 適度な使用:Cleaner主に特別なシナリオで使用されます。例えば、リークのない非 Java リソースを確保する場合です。単純なリソース管理には、try-with-resourcesの方がより適しています。
  • 制御不能な実行時間:Cleanerのクリーンアップタスクはfinalizefinalize より迅速ですが、クリーンアップタスクの正確な実行時間は依然としてガベージコレクションの時間に依存するため、時間的制約が厳しいリソース管理には適していません。
  • リソース集約型のクリーンアップタスクは慎重に:Cleaner 内でCleaner過度に複雑または長時間の操作を実行しないようにしてください。ガベージコレクションのパフォーマンスに影響を与えないようにするためです。

総じて、java.lang.ref.CleanerCleaner は Java で推奨されるリソースクリーンアップツールであり、効率的で信頼性の高いリソース管理方法を提供します。

その他の拡張