2015-01-30 3 views
1

Листинг 3.7. Неявно разрешить эту ссылку для Escape. Не делай этого.Как листинг 3.7 работает в Java-параллелизме на практике?

public class ThisEscape { 
public ThisEscape(EventSource source) { 
    source.registerListener(
    new EventListener() { 
    public void onEvent(Event e) { 
     doSomething(e); 
    } 
    } 
    } 
} 
} 

Цитирование «Окончательный механизм, с помощью которого объект или его внутреннее состояние может быть опубликован опубликует экземпляр внутреннего класса, как показано на ThisEscape в листинге 3.7. Когда ThisEscape публикует EventListener, он неявно публикует ограждающих ThisEscape экземпляра, а также, поскольку экземпляры внутренних классов содержат скрытую ссылку на ограждающих например "

Мой вопрос:. Где эта скрытая ссылка и как это может быть использовано?

+0

См. Http: //www.javaspecialists.eu/archive/Issue192.html. – Dave

ответ

3

«скрытая ссылка» - это неявная переменная, которую имеет любой нестатический внутренний класс, который позволяет ей ссылаться на члены своего внешнего класса.

Рассмотрим слегка измененную версию этого класса:

public class ThisEscape { 
    private final List<EventSource> listOfEvents; 
    public ThisEscape(EventSource source) { 
    source.registerListener(
     new EventListener() { 
     public void onEvent(Event e) { 
      doSomething(e); 
      listOfEvents.add(e); //The "hidden reference" is what allows this inner class 
           //to use the parent's "listOfEvents" member variable 
     } 
     } 
    } 
    Thread.sleep(5000); //This would need a try/catch - skipping that 
    listOfEvents = new ArrayList<EventSource>(); 
    } 
} 

В этом случае, очевидно, что проблема - если какое-либо событие передается EventListener до Thread.sleep отделки, listOfEvents все равно будет нулевым , и вы получите NullPointerException.

Из-за способа Java обрабатывает видимость памяти между потоками, вы могли бы еще иметь такой же эффект (хотя это было бы гораздо меньше шансов), даже если вы удалили вызов sleep, и даже если вы переместили инициализацию listOfEvents перед тем звонок в registerListener!

Что касается «эксплуатации» этого, это будет сильно зависеть от контекста, но любой экземпляр вышеуказанного шаблона, безусловно, является потенциальной ошибкой, которая может произойти, даже если злоумышленник не пытается ее использовать.

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