Java : Cleaner - API使用例
Cleaner (Java SE 18 & JDK 18) の使用例まとめです。
だいたいのメソッドを網羅済みです。
API仕様のおともにどうぞ。
概要
Cleanerクラスを使うと、対象となるオブジェクトがクリアされるときに、登録しておいたアクションを実行できます。
イメージとしては Objectクラス の finalize に近いです。
Cleanerクラスは、内部的には ファントム参照 を利用しています。
ファントム参照がクリアされるタイミングで (つまり対象オブジェクトが finalize されたあと) 、登録したアクションを実行します。
class Foo {
@SuppressWarnings("removal")
@Override
protected void finalize() {
System.out.println("Finalize!");
}
}
var foo = new Foo();
final var cleaner = Cleaner.create();
cleaner.register(foo, () -> {
System.out.println("Clean!");
final var current = Thread.currentThread();
System.out.printf(" (thread id = %d, daemon = %b)%n", current.getId(), current.isDaemon());
});
System.out.println("-- start -- (thread id = " + Thread.currentThread().getId() + ")");
foo = null;
System.out.println("-- gc --");
System.gc();
TimeUnit.SECONDS.sleep(3);
System.out.println("-- sleep --");
System.out.println("-- gc --");
System.gc();
TimeUnit.SECONDS.sleep(3);
System.out.println("-- sleep --");
// 結果
// ↓
//-- start -- (thread id = 1)
//-- gc --
//Finalize!
//-- sleep --
//-- gc --
//Clean!
// (thread id = 19, daemon = true)
//-- sleep --
個人的には、Cleaner クラスを使わずに、AutoCloseable と try-with-resources文 で確実に後処理するのをおすすめします。
メソッド
static Cleaner create ()
class Foo {
@SuppressWarnings("removal")
@Override
protected void finalize() {
System.out.println("Finalize!");
}
}
var foo = new Foo();
final var cleaner = Cleaner.create();
cleaner.register(foo, () -> {
System.out.println("Clean!");
final var current = Thread.currentThread();
System.out.printf(" (thread id = %d, daemon = %b)%n", current.getId(), current.isDaemon());
});
System.out.println("-- start -- (thread id = " + Thread.currentThread().getId() + ")");
foo = null;
System.out.println("-- gc --");
System.gc();
TimeUnit.SECONDS.sleep(3);
System.out.println("-- sleep --");
System.out.println("-- gc --");
System.gc();
TimeUnit.SECONDS.sleep(3);
System.out.println("-- sleep --");
// 結果
// ↓
//-- start -- (thread id = 1)
//-- gc --
//Finalize!
//-- sleep --
//-- gc --
//Clean!
// (thread id = 19, daemon = true)
//-- sleep --
static Cleaner create (ThreadFactory threadFactory)
class Foo {
@SuppressWarnings("removal")
@Override
protected void finalize() {
System.out.println("Finalize!");
}
}
var foo = new Foo();
final var cleaner = Cleaner.create(r -> new Thread(r, "ABC"));
cleaner.register(foo, () -> {
System.out.println("Clean!");
final var current = Thread.currentThread();
System.out.printf(" (thread id = %d, name = %s, daemon = %b)%n",
current.getId(), current.getName(), current.isDaemon());
});
System.out.println("-- start -- (thread id = " + Thread.currentThread().getId() + ")");
foo = null;
System.out.println("-- gc --");
System.gc();
TimeUnit.SECONDS.sleep(3);
System.out.println("-- sleep --");
System.out.println("-- gc --");
System.gc();
TimeUnit.SECONDS.sleep(3);
System.out.println("-- sleep --");
// 結果
// ↓
//-- start -- (thread id = 1)
//-- gc --
//Finalize!
//-- sleep --
//-- gc --
//Clean!
// (thread id = 19, name = ABC, daemon = true)
//-- sleep --
Cleaner.Cleanable register (Object obj, Runnable action)
class Foo {
}
final var foo = new Foo();
final var cleaner = Cleaner.create();
final var cleanable = cleaner.register(foo, () -> {
System.out.println("Clean!");
final var current = Thread.currentThread();
System.out.printf(" (thread id = %d, daemon = %b)%n", current.getId(), current.isDaemon());
});
System.out.println("-- start -- (thread id = " + Thread.currentThread().getId() + ")");
cleanable.clean();
// 結果
// ↓
//-- start -- (thread id = 1)
//Clean!
// (thread id = 1, daemon = false)