从内存编译java类失败,cmd和netbean ide中输出两个不同的错误
我试图在不保存到文件的情况下运行java类,为此我使用从内存编译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
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的引用,以便更清楚地说明我所指的编译器。