2014-04-07 5 views
0

Предположим, что я создал класс MyClass, который реализует Closable. Поэтому в методе close() я собираюсь освободить некоторые важные ресурсы. Ну, так как это очень важные источники, я создал некоторую сеть безопасности (как рекомендовано в Effective Java). Вот оно:Могу ли я избежать использования Reflection во время финализации с помощью PantomReferences?

protected void finalize(){ 
if (/*user didn't call close() method by himself*/){ 
    close(); 
} 
} 

Сначала я был очень счастлив, но потом я прочитал, что финализации не так здорово, и что есть такой крутой инструмент, как PhantomReference. Поэтому я решил изменить свой код, чтобы использовать метод PhantomReference вместо метода finalize(). Я создал CustomPantom extends 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 
} 
} 

Так как я вижу единственный способ, которым я могу получить ссылку на мой объект является использование отражения и получить, если из поля референта, который находится в справочном классе. Это единственный способ вызвать MyClass.close() из метода очистки?

P.S. Я не размещал весь код здесь, но я тестировал его, и все работает нормально. ReferenceQueue заполняется PhantomReferences, а затем я могу получить их один за другим и вызвать метод очистки. Но я не понимаю, как решить эту проблему без использования рефлексии.

ответ

1

Вы не можете сделать что-то подобное с фантомными ссылками, и даже размышления не помогут. Вы получите только ссылку в ReferenceQueue после того, как GC уже произошла, поэтому больше нет объекта для вызова close().

Одна вещь, которую вы можете сделать - хорошая идея, по сути, состоит в том, чтобы использовать PhantomReference, чтобы выбросить ошибку, говоря, что вы должны были позвонить close() напрямую и не сделали этого. Например, у вас может быть объект-референс со ссылкой на ваш CustomPhantom и вызвать метод CustomPhantom.setCleanedUp(true). Затем в вашем CustomPhantom, если вы находитесь в ReferenceQueue и не очищены, вы можете отобразить предупреждение.

+0

Спасибо за ответ. Я был смущен этой ссылкой http://www.erpgreat.com/java/phantomreference-and-finalization.htm. Парень сказал, что мы можем воскресить объект из PhantomReference, используя Reflection –

0

Поскольку был принят ответ, я просто добавляю дополнительную информацию.

При использовании API для отражения Java для изучения класса PantomReferences, вы не получите поле референта. NoSuchFieldException будет выброшен.

Смежные вопросы