清单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实例,因为内部类实例包含一个 对封闭实例的隐藏引用。 "
我的问题是: 这个隐藏的参考在哪里?如何利用它?
答案 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.sleep
,listOfEvents
仍然为空,并且你会得到NullPointerException
。
由于Java处理跨线程的内存可见性的方式,即使你删除了对sleep
的调用,即使你移动了初始化,你仍然可以产生类似的效果(尽管它的可能性会小得多)在致电listOfEvents
之前的registerListener
!
至于&#34;剥削&#34;这在很大程度上取决于上下文 - 但上述模式的任何实例肯定是可能发生的潜在错误,即使没有攻击者试图利用它。