为什么未在正确的行上报告NPE

问题描述

运行以下内容

public class NPESample {

  String value;

  public static void main(String[] args) {
    NPESample npeSample = null;
    "foo"
        .replaceAll(
            "f",npeSample.value);
  }
}

会给:

Exception in thread "main" java.lang.NullPointerException
    at NPESample.main(NPESample.java:9)

报告的行(7)是"foo"行,而不是发生NPE的实际行(10)npeSample.value

这是为什么?调试代码时,我感到惊讶,并被代码中报告的“错误”行号所吸引。

要重现,请运行以下命令:

cat > ./NPESample.java <<DELIM
public class NPESample {

  String value;

  public static void main(String[] args) {
    NPESample npeSample = null;
    "foo"
        .replaceAll(
            "f",npeSample.value);
  }
}
DELIM

javac NPESample.java
java NPESample

输出为:

Exception in thread "main" java.lang.NullPointerException
    at NPESample.main(NPESample.java:7)
javac -version
javac 13.0.1
java -version
openjdk version "13.0.1" 2019-10-15
OpenJDK Runtime Environment (build 13.0.1+9)
OpenJDK 64-Bit Server VM (build 13.0.1+9,mixed mode,sharing)

解决方法

对我来说,这看起来不像是个错误。具体来说,似乎自由地允许映射不为一,as the SPEC says

也就是说,LineNumberTable属性可以一起代表源文件的给定行,并且不必与源行一对一

即使JDK-15报告错误的行:

由于“ npeSample”为空,因此无法读取字段“值”

9行。