Warning: file_get_contents(/data/phpspider/zhask/data//catemap/9/java/307.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
从内存编译java类失败,cmd和netbean ide中输出两个不同的错误_Java - Fatal编程技术网

从内存编译java类失败,cmd和netbean ide中输出两个不同的错误

从内存编译java类失败,cmd和netbean ide中输出两个不同的错误,java,Java,我试图在不保存到文件的情况下运行java类,为此我使用javax.tools.JavaCompiler 在这里我找到了一个 但是当我运行这段代码时,我得到了两个不同的输出。ide和cmd中的java版本都是1.8.0\u 31 这在netbeans IDE 8.0.2版中 这是50号线 Class.forName("HelloWorld").getDeclaredMethod("main", new Class[]{String[].class}) 这是cmd输出 第33行是 Compil

我试图在不保存到文件的情况下运行java类,为此我使用
javax.tools.JavaCompiler

在这里我找到了一个

但是当我运行这段代码时,我得到了两个不同的输出。ide和cmd中的java版本都是
1.8.0\u 31
这在netbeans IDE 8.0.2版中

这是50号线

Class.forName("HelloWorld").getDeclaredMethod("main", new Class[]{String[].class})
这是
cmd
输出

第33行是

CompilationTask task = compiler.getTask(null, null, diagnostics, null, null, compilationUnits);
我想知道获得两种不同输出的原因

这是我使用的代码。这与上面答案的代码几乎相同。但我在一个中删除了多个catch块

import java.io.IOException;
import java.io.PrintWriter;
import java.io.StringWriter;
import java.lang.reflect.InvocationTargetException;
import java.net.URI;
import java.util.Arrays;
import javax.tools.Diagnostic;
import javax.tools.DiagnosticCollector;
import javax.tools.JavaCompiler;
import javax.tools.JavaFileObject;
import javax.tools.SimpleJavaFileObject;
import javax.tools.ToolProvider;
import javax.tools.JavaCompiler.CompilationTask;
import javax.tools.JavaFileObject.Kind;

public class CompileSourceInMemory {

    public static void main(String args[]) throws IOException {
        JavaCompiler compiler = ToolProvider.getSystemJavaCompiler();
        DiagnosticCollector<JavaFileObject> diagnostics = new DiagnosticCollector<JavaFileObject>();

        StringWriter writer = new StringWriter();
        PrintWriter out = new PrintWriter(writer);
        out.println("public class HelloWorld {");
        out.println("  public static void main(String args[]) {");
        out.println("    System.out.println(\"This is in another java file\");");
        out.println("  }");
        out.println("}");
        out.close();
        JavaFileObject file = new JavaSourceFromString("HelloWorld", writer.toString());

        Iterable<? extends JavaFileObject> compilationUnits = Arrays.asList(file);
        CompilationTask task = compiler.getTask(null, null, diagnostics, null, null, compilationUnits);

        boolean success = task.call();
        for (Diagnostic diagnostic : diagnostics.getDiagnostics()) {
            System.out.println(diagnostic.getCode());
            System.out.println(diagnostic.getKind());
            System.out.println(diagnostic.getPosition());
            System.out.println(diagnostic.getStartPosition());
            System.out.println(diagnostic.getEndPosition());
            System.out.println(diagnostic.getSource());
            System.out.println(diagnostic.getMessage(null));

        }
        System.out.println("Success: " + success);

        if (success) {
            try {
                Class.forName("HelloWorld").getDeclaredMethod("main", new Class[]{String[].class})
                        .invoke(null, new Object[]{null});
            } catch (Exception e) {
                e.printStackTrace();
            }
        }
    }
}

class JavaSourceFromString extends SimpleJavaFileObject {

    final String code;

    JavaSourceFromString(String name, String code) {
        super(URI.create("string:///" + name.replace('.', '/') + Kind.SOURCE.extension), Kind.SOURCE);
        this.code = code;
    }

    @Override
    public CharSequence getCharContent(boolean ignoreEncodingErrors) {
        return code;
    }
}
import java.io.IOException;
导入java.io.PrintWriter;
导入java.io.StringWriter;
导入java.lang.reflect.InvocationTargetException;
导入java.net.URI;
导入java.util.array;
导入javax.tools.Diagnostic;
导入javax.tools.DiagnosticCollector;
导入javax.tools.JavaCompiler;
导入javax.tools.JavaFileObject;
导入javax.tools.SimpleJavaFileObject;
导入javax.tools.ToolProvider;
导入javax.tools.JavaCompiler.CompilationTask;
导入javax.tools.JavaFileObject.Kind;
公共类CompileSourceInMemory{
公共静态void main(字符串args[])引发IOException{
JavaCompiler=ToolProvider.getSystemJavaCompiler();
DiagnosticCollector diagnostics=新建DiagnosticCollector();
StringWriter编写器=新的StringWriter();
PrintWriter out=新的PrintWriter(writer);
println(“公共类HelloWorld{”);
println(“publicstaticvoidmain(stringargs[]){”);
println(“System.out.println(\“这在另一个java文件中\”);”;
out.println(“}”);
out.println(“}”);
out.close();
JavaFileObject file=newJavaSourceFromString(“HelloWorld”,writer.toString());

Iterable我无法重现您的第一个错误:

$ ~/jdk1.8.0_25/bin/java CompileSourceInMemory
Success: true
This is in another java file
在您的案例中,尝试找出从终端或命令行调用了哪个java。 第二个问题与NetBeans/编译器输出已编译类的位置有关。它是项目的根,因此类路径需要调整:

if (success) {
  try {
    URL[] classpathExt = {new File("/home/[your name]/NetBeansProjects/JavaApplication2/").toURI().toURL()};
    URLClassLoader loader = new URLClassLoader(classpathExt, null);
    Class.forName("HelloWorld", true, loader).getDeclaredMethod("main", new Class[]{String[].class})
        .invoke(null, new Object[]{null});
  } catch (Exception e) {
    e.printStackTrace();
  }
}

有趣的是,
~/NetBeansProjects/JavaApplication2/
不起作用,必须指定完整路径。对于Windows,您将使用
C:\\User\\以此类推\\

第33行的cmd问题可能是因为命令行类路径中不存在tools.jar(因此
编译器
为空).ToolProvider.getSystemJavaCompiler()返回的编译器来自此jar,因此如果tools.jar不在类路径上,它将返回null。然后在第33行取消引用此编译器以导致NPE

也许您从命令行运行的编译器只安装了JRE,而没有安装JDK?我想NetBeans IDE会自动为您包含JDK库


然而,它的类加载器似乎无法加载java源代码,正如Filip Bulovic提到的:您可以创建一个新的
URLClassLoader
,将
ToolProvider.getSystemJavaCompiler()返回的编译器所在的目录添加到其中
放入编译后的代码。也可以使用
ToolProvider.getSystemToolClassLoader()提供的类加载器
加载
HelloWorld
类。

您可能需要使用com.mypackage之类的包名给出类的完整路径。HelloWorld是net beans JDK版本和在环境变量中配置的版本(在cmd中使用)相同?我在eclipse中遇到了相同的错误,但在Java1中编译成功。6@kbird我没有添加包声明。@KalyanChavali是的,两者都是相同的,它是
1.8.0\u 31
您必须创建[另一个类加载器][1]才能使用内存中的类。[1]:感谢您的回复。我在桌面上创建了一个文件夹,并在其中创建了一个类,然后使用cmd运行。我没有从cmd运行netbeans类。不客气。答案的第一部分是原样的代码,不涉及netbeans。我记得在一些公司,桌面文件夹实际上是远程共享的,可以帮助他们进行备份。是吗在工作中这样做?没有远程共享,这是我个人的一个。这段代码在cmd和netbeans中对您有效吗?代码编译时从终端/命令行开始工作,因为需要在路径中调整netbeans。不知道为什么在您的操作系统上从命令行无法工作。谢谢您的回复“也许系统编译器只安装了JRE,而没有安装JDK?”我不明白这一部分,你能解释一下“ToolProvider.getSystemJavaCompiler()返回的编译器吗'来自tools.jar。仅当您安装JDK时,才会安装它。如果从命令行运行的编译器是作为JRE安装的一部分安装的,则您将没有tools.jar,并且“ToolProvider.getSystemJavaCompiler()返回的“JavaCompiler”'将为空。我认为这就是从命令行运行编译器时发生的情况。您选择的是仅限JRE的编译器。我稍微重写了答案,以删除您提到的行中对system compiler的引用,以便更清楚地说明我所指的编译器。