清单3.7实际上是如何在java并发中工作的?
清单3.7。隐式地允许此引用转义。不要这样做清单3.7实际上是如何在java并发中工作的?,java,concurrency,Java,Concurrency,清单3.7。隐式地允许此引用转义。不要这样做 public class ThisEscape { public ThisEscape(EventSource source) { source.registerListener( new EventListener() { public void onEvent(Event e) { doSomething(e); } } } } } 引用 发布对象或其内部状态的最后一种机制是发布内部类实例
public class ThisEscape {
public ThisEscape(EventSource source) {
source.registerListener(
new EventListener() {
public void onEvent(Event e) {
doSomething(e);
}
}
}
}
}
引用
发布对象或其内部状态的最后一种机制是发布内部类实例,如清单3.7中的此Escape所示。当ThisEscape发布EventListener时,它也隐式发布封闭的ThisEscape实例,因为内部类实例包含
对封闭实例的隐藏引用
我的问题是:
这个隐藏引用在哪里?如何利用它?隐藏引用是任何非静态内部类都具有的隐式变量,允许它引用其外部类的成员 考虑对该类稍加修改的版本:
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>();
}
}
在本例中,问题很明显-如果在Thread.sleep完成之前将任何事件传递给EventListener,listOfEvents仍将为null,您将得到一个NullPointerException
由于Java处理跨线程内存可见性的方式,您仍然可以获得类似的效果,尽管即使您删除了对睡眠的调用,并且即使您在调用registerListener之前移动了ListoEvents的初始化,这种情况也不太可能发生
就利用这一点而言,这在很大程度上取决于上下文-但上述模式的任何实例都肯定是可能发生的潜在错误,即使没有攻击者试图利用它。隐藏引用是任何非静态内部类所具有的隐式变量,允许它引用其外部类的成员 考虑对该类稍加修改的版本:
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>();
}
}
在本例中,问题很明显-如果在Thread.sleep完成之前将任何事件传递给EventListener,listOfEvents仍将为null,您将得到一个NullPointerException
由于Java处理跨线程内存可见性的方式,您仍然可以获得类似的效果,尽管即使您删除了对睡眠的调用,并且即使您在调用registerListener之前移动了ListoEvents的初始化,这种情况也不太可能发生
就利用这一点而言,这在很大程度上取决于上下文-但上述模式的任何实例都肯定是可能发生的潜在错误,即使攻击者没有试图利用它。请参阅:请参阅: