JVM如何知道何时引发NullPointerException

Exa*_*gon 0 java compiler-construction jvm nullpointerexception

Java虚拟机如何知道何时引发NullPointerException?它会在我对某个对象调用的每个方法之前检查是否该对象为null,以检查是否必须抛出NullPointerException吗?如果是这样,这真的慢吗?

Ste*_*n C 5

JVM可以使用两种方法来“检测”空值。

  • JVM可以在使用引用之前显式测试引用的值。这代表了开销,但是JIT编译器可以优化一些null测试。例如:

    1. 对其进行方法调用this不能提供NPE。
    2. 如果p不是易失的,则可以这样写:

      if (p != null) { p.something(); }
      
      Run Code Online (Sandbox Code Playgroud)

      p.something()不需要隐式的空值签入。

    3. 如果p不是易失的,则可以这样写:

      p.something();
      p.somethingElse();
      
      Run Code Online (Sandbox Code Playgroud)

      然后不需要第二个隐式空检查。

    还值得注意的是,空测试可能会对具有深层管道的CPU的性能产生零影响。这将取决于本地化的内存访问模式,以及编译器/硬件是否能够安排测试指令与(例如)内存提取或存储重叠。

  • JVM可以使用虚拟内存硬件实现空检查。JVM将其虚拟地址空间中的第零页映射到不可读+不可写的页面。由于null表示为零,因此当Java代码尝试取消引用时,null这将尝试访问不可寻址的页面,并导致OS向JVM传递“ segfault”信号。JVM的segfault信号处理程序可以捕获此错误,找出代码在何处执行,然后在相应线程的堆栈上创建NPE并将其抛出。

    这很复杂并且相当昂贵。但是,没关系,NPE非常稀有。

  • 在热点中,两种方法都基于类型/空性分析信息使用 (2认同)