列表3.7如何在实践中使用java并发?

时间:2015-01-30 13:59:39

标签: java concurrency

清单3.7。隐式允许此引用转义。不要这样做。

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

引用 "可以发布对象或其内部状态的最终机制是发布内部类实例,如清单3.7中的ThisEscape所示。当ThisEscape发布EventListener时,它也隐式发布封闭的ThisEscape实例,因为内部类实例包含一个 对封闭实例的隐藏引用。 "

我的问题是: 这个隐藏的参考在哪里?如何利用它?

1 个答案:

答案 0 :(得分: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.sleeplistOfEvents仍然为空,并且你会得到NullPointerException

由于Java处理跨线程的内存可见性的方式,即使你删除了对sleep的调用,即使你移动了初始化,你仍然可以产生类似的效果(尽管它的可能性会小得多)在致电listOfEvents之前的registerListener

至于&#34;剥削&#34;这在很大程度上取决于上下文 - 但上述模式的任何实例肯定是可能发生的潜在错误,即使没有攻击者试图利用它。