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 の実行を促す(クリーンアップがすぐに実行されるとは限らない)
}
}
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 で推奨されるリソースクリーンアップツールであり、効率的で信頼性の高いリソース管理方法を提供します。