19 Aralık 2017 Salı

PhantomReference Sınıfı

Giri
Açıklaması şöyle
Phantom References exist so we can track when an object is collected by the GC. They don’t hold any reference to the object (hence the name) and don’t interfere with its life span (no matter what kind of reference we are using to reach it). This is the new finalization mechanism of the JVM and the previous one (the finalize method) is now deprecated and should not be used.
Bu sınıfı hiç kullanmadım. Native C++ kaynaklarını temizlemek için kullanılabilir.

constructor
Şöyle yaparız.
ReferenceQueue<Object> garbageCollectedObjectsQueue = new ReferenceQueue<>();

Object referent = ...;
new PhantomReference<Object> (referent, garbageCollectedObjectsQueue);
Örnek
Elimizde şöyle bir arayüz olsun
public interface Cleanable {
  void clean();
}
Bu arayüzü kullanmayı kolaylaştıran şöyle bir sınıf olsun
public class Cleaner {
 
  public static Cleanable register(Object o, Runnable r) {
    CleanerReference c = new CleanerReference(o,r);
    phantomReferences.add(c);
    return c;
  }
  private static final Set<CleanerReference> phantomReferences
                                             = ConcurrentHashMap.newKeySet();
  private static final ReferenceQueue<Object> garbageCollectedObjectsQueue
                                              = new ReferenceQueue<>();

  static final class CleanerReference extends PhantomReference<Object>
                                        implements Cleanable {
    private final Runnable cleaningAction;

    CleanerReference(Object referent, Runnable action) {
      super(referent, garbageCollectedObjectsQueue);
      cleaningAction = action;
    }
    public void clean() {
      if(phantomReferences.remove(this)) {
        super.clear();
        cleaningAction.run();
      }
    }
  }
  public static void deleteOrphanedNativePeerObjects() {
    CleanerReference reference;
    while((reference=(CleanerReference)garbageCollectedObjectsQueue.poll()) != null) {
      reference.clean();
    }
  }
}
Kullanmak için şöyle yaparız.
private long _nativeHandle;
Cleaner.Cleanable cleanable;

public WorkViewModel(Database database, int workId) {
  _nativeHandle = ...;
  cleanable = createCleanable(this, _nativeHandle);
}
private static Cleaner.Cleanable createCleanable(Object o, long _nativeHandle) {
  return Cleaner.register(o, () -> delete(_nativeHandle));
}

static native void delete(long nativeHandle);
get metodu
Örnek
Şöyle yaparız
Object object = new Object();

ReferenceQueue<Object> referenceQueue = new ReferenceQueue<>();
PhantomReference<Object> phantomReference = new PhantomReference<>(object,referenceQueue);

object = null;
System.gc(); //request gc

System.out.println(phantomReference.get()); // always null
        
Reference<?> referenceFromQueue;
while ((referenceFromQueue = referenceQueue.poll()) != null) {
  // This line will be reached only when the object is collected
  System.out.println(referenceFromQueue);
}

Hiç yorum yok:

Yorum Gönder