Warning: file_get_contents(/data/phpspider/zhask/data//catemap/8/logging/2.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
清单3.7实际上是如何在java并发中工作的?_Java_Concurrency - Fatal编程技术网

清单3.7实际上是如何在java并发中工作的?

清单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); } } } } } 引用 发布对象或其内部状态的最后一种机制是发布内部类实例

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

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的初始化,这种情况也不太可能发生

就利用这一点而言,这在很大程度上取决于上下文-但上述模式的任何实例都肯定是可能发生的潜在错误,即使攻击者没有试图利用它。

请参阅:请参阅: