Буду ли я избегать использования 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 будет брошено.

Другие вопросы по тегам