Буду ли я избегать использования Reflection во время финализации с PantomReferences?
Допустим, я создал класс MyClass, который реализует Closable. Так что в методе close() я собираюсь освободить несколько очень важных ресурсов. Ну, так как это очень важные источники, я создал какую-то сеть безопасности (как рекомендуется в Effective Java). Вот:
protected void finalize(){
if (/*user didn't call close() method by himself*/){
close();
}
}
Сначала я был очень счастлив, но позже я прочитал, что финализатор не такой крутой и что есть такой классный инструмент, как PhantomReference. Поэтому я решил изменить свой код для использования метода PhantomReference вместо метода finalize(). Я создал CustomPantom расширяет PhantomRefernce. Вот:
public class CustomPhantom extends PhantomReference {
//Object cobj;
public CustomPhantom(Object referent, ReferenceQueue q) {
super(referent, q);
//this.cobj = referent; can't save the refference to my object in a class field,
// because it will become strongly rechable
//and PhantomReference won't be put to the reference queue
}
public void cleanup(){
//here I want to call close method from my object,
//but I don't have a reference to my object
}
}
Так что, как я вижу, единственный способ получить ссылку на свой объект - это использовать отражение и получить if из поля референта, которое находится в классе Reference. Это единственный способ вызвать MyClass.close() из метода очистки?
PS Я не разместил весь код здесь, но я проверил его, и все работает отлично. ReferenceQueue заполняется PhantomReferences, и тогда я могу получить их один за другим и вызвать метод очистки. Но я не вижу, как решить вышеупомянутую проблему без использования отражения.
2 ответа
Вы не можете сделать что-то подобное с призрачными ссылками, и даже рефлексия не поможет. Вы получаете только ссылку в ReferenceQueue
после того, как GC уже произошел, поэтому больше нет объекта для вызова close()
на.
Одна вещь, которую вы можете сделать - хорошая идея, на самом деле - это использовать PhantomReference
выдать ошибку, сказав, что вы должны были позвонить close()
прямо так и не сделал. Например, у вас может быть референтный объект, имеющий ссылку на ваш CustomPhantom
и позвонить CustomPhantom.setCleanedUp(true)
метод. Тогда в вашем CustomPhantom
, если вы в ReferenceQueue
и он не очищен, вы можете отобразить предупреждение.
Так как был принят ответ, я просто добавляю больше информации.
При использовании API отражения Java для проверки класса PantomReferences вы не получите поле референта. NoSuchFieldException будет брошено.