接口工具的run()方法在JDK 9中抛出NullPointerException

时间:2018-02-02 18:33:41

标签: java nullpointerexception java-8 java-9 java-compiler-api

//以下是Hello.java文件。

public class Hello{
    public static void main(String... s){
        System.out.println("hello world");
    }
}

我正在尝试使用Java Compiler API编译上面的类,如下所示:

import javax.tools.*;
public class CallingJavaCompiler{
    public static void main(String... s){
        JavaCompiler comp = ToolProvider.getSystemJavaCompiler();
        int i = comp.run(System.in,System.out,System.err,"Hello.java");
        System.out.println(i);
    }
}

在执行CallingJavaCompiler类(使用JDK 9 )时,它会在run方法中抛出java.lang.NullPointerException。我无法理解为什么当有字符串类型参数时它会抛出异常?

这是执行它时我得到的堆栈跟踪:

Exception in thread "main" java.lang.NullPointerException
    at CallingJavaCompiler.main(CallingJavaCompiler.java:5)

另一方面,在 JDK 8 中执行相同的程序,即CallingJavaCompiler,它正在执行而没有任何运行时异常

请帮助我理解为什么在使用JDK 9执行它时会抛出Null Pointer Exception(NPE)?

注意:我正在使用javac 9.0.4编译上面的代码并使用java版本9.0.4执行它。在使用这些版本进行编译和执行时,我得到的是NPE,但不是JDK 8。

2 个答案:

答案 0 :(得分:4)

将Hello.java替换为Hello.java文件的完整路径(例如C:\ Test \ Hello.java)。无论如何,即使Hello.java的路径错误,我也没有得到NullPointerException。

<强>更新

我能够重现你的java.lang.NullPointerException错误。使用JRE而不是JDK运行程序时出现。这样,就没有找到编译器,因为编译器仅在JDK版本中可用。

<强> UPDATE2

所以你使用命令行来运行程序。

使用%jdk_home%/bin/java执行时,您正在使用JDK,而使用%jdk_home%/jre/bin/java执行时,您使用的是JRE。

我看到您使用JDK 9.0.1进行编译并使用JRE 9.0.4运行。为了使它工作,执行如下:

%JDK 9.0.1 home%/bin/java CallingJavaCompiler

答案 1 :(得分:3)

来自ToolProvider#getSystemJavaCompiler的文档:

  

如果该模块可用,则此实现返回jdk.compiler模块提供的编译器,否则返回null。

我怀疑您的jdk.compiler模块由于某种原因不可用(您可能正在使用JRE 9而不是JDK 9运行程序),因此您可能会收到NullPointerException。可以肯定的是,我建议将其添加到module-info.java,即使它似乎并不是必需的。

module Hello {
    requires jdk.compiler;
}

无论如何,我能够通过提供Hello.java的完整路径来解决您的问题,如下所示。这适用于Windows;如果您使用任何其他操作系统,则应使用File.separatorSystem.getProperty("file.separator")而不是\\

JavaCompiler comp = ToolProvider.getSystemJavaCompiler();

int i = comp.run(System.in, System.out, System.err,"src\\main\\java\\Hello.java");

System.out.println(i);

输出:

  

0

注意:路径从项目的根目录(源文件夹的父目录src)开始。请记住通过在必要时附加到目录来包含任何包。