Item 8. ロケータとクリーナーの使用を避ける


Javaは2つのオブジェクトの消滅者を提供します.これはロケータとクリーナーです.この2種類は避けたほうがいいです.
ターミナルは深刻な危険性を有する.パフォーマンスの低下、エラー動作、移植性の問題など.
finalizerおよびclearは、時間通りに実行する必要があるタスクには使用できません.スレッドの優先度が低いため、実行する機会が得られにくいため、すぐに実行する必要がある操作に使用すると、OutOfMemoryErrorの主犯になり続けます.
また、Java言語宣言はfinalizerまたはclearの実行時間と実行時間を保証しません.作業が正常に完了せず、プログラムが中断する可能性があります.したがって、データベース内のリソースをトリガするために使用するべきではありません.これらのリソースは、ステータスを永続的に変更します.
ターミナルの副作用はまだあります.操作中に発生した異常を直ちに無視し、処理する操作が残っていても終了します.したがって、不完全なオブジェクトが作成される可能性があります.これらの不安全なオブジェクトは攻撃にさらされる可能性があります.
finalizerとclearには深刻なパフォーマンスの問題もあります.単純なオブジェクトの作成、ゴミ収集器によるオブジェクトの収集時間、およびこの2つの消滅プログラムを使用してオブジェクトを破壊する時間の差は50倍近くあります.
代わりの妙策は何だろう.AutoCloseableを実装し、クライアントがインスタンスを使い切った後にcloseメソッドを呼び出します.try-with-resourcesを使用して、同時に異常が発生した場合に正しく終了する必要があります.
では、この2つの使えない消滅者をどこで使うべきか.使用例は2つあります.1つは、クライアントがcloseを呼び出すことができない場合のセキュリティネットワークです.優先度が低く、いつ実行されるか分からないが、いっそしないよりも最後の砦として使ったほうがいい.
第2の例は、ネイティブ・ピア(ネイティブ・ピア)に関連付けられたオブジェクトから来ている.ネイティブピアとは、汎用Javaオブジェクトがネイティブメソッドを介して機能を委任するネイティブオブジェクトを指す.
本機対等はゴミ収集器の範囲内ではないため、クリーナーやターミネータとして非常に適しています.本機のピアツーピアデバイスに十分なリソースがない場合にのみ、性能の低下に耐えられる.
次に、AutoClosableがセキュリティネットワークとしてCleanerを使用する例を示します.
public class Room implements AutoCloseable{
    private static final Cleaner cleaner = Cleaner.create();
	// 청소가 필요한 자원, 절대 Room을 참조해서는 안 된다!
    private static class State implements Runnable{
        int numJunkPiles; // 방(Room) 안의 쓰레기 수

        State(int numJunkPiles){
            this.numJunkPiles = numJunkPiles;
        }

		// close 메서드나 cleaner가 호출한다.
        @Override
        public void run() {
            System.out.println("방 청소");
            numJunkPiles = 0;
        }
    }
    
    // 방의 상태. cleanable 과 공유한다.
    private final State state;

	// cleanable 객체. 수거 대상이 되면 방을 청소한다.
    private final Cleaner.Cleanable cleanable;

    public Room(int numJunkPiles){
        state = new State(numJunkPiles);
        cleanable = cleaner.register(this, state);
    }


    @Override
    public void close() throws Exception {
        cleanable.clean();
    }
}
コードを簡単に説明します.StateではnumJunkPilesが残りのリソースであり、close()を呼び出すとclearによってリソースが消去されます.
クライアントがclose()を呼び出すのを忘れた場合、ゴミ収集器はリカバリスタジオでStateのrun()を呼び出す.
ステータスインスタンスは、[ルーム](Working)インスタンスを参照することはできません.これは、ループ参照が生成され、ゴミ収集器がスタジオインスタンスを復元する機会がないためです.
スタジオのclearがセキュリティネットワークとしてのみ使用され、クライアントがtry-with-resourcesブロックを使用してスタジオの作成を包囲している場合、自動クリーンアップは必要ありません.
public class Adult{
    public static void main(string[] args){
    	try(Room myRoom = new Room(7)){
        	System.out.println("안녕");
        }
    }
}
上のコードは「こんにちは」を出力した後、「部屋の掃除」を出力します.