问题
I'm trying to write a java program with an interface that allows the user to create .java file and compile and run it (essentially a very simplistic IDE). I'm using java swing for the gui and have so far been able to compile a .java file from within the interface into a .class file. I've been researching how to run a .class file from within java code but have found a wide range of answers which I haven't been able to get working. Here is the relevant code for compilation:
File javaFile = new File( "test1.java" );
String code = entry.getText(); // get text entered by user in GUI
try{
PrintWriter writer = new PrintWriter( javaFile ); // write text to .java file
writer.print( code );
writer.close();
}
catch( FileNotFoundException e ){
System.err.println( e );
}
JavaCompiler compiler = ToolProvider.getSystemJavaCompiler();
List<File> sourceFileList = new ArrayList<File>();
sourceFileList.add( javaFile );
StandardJavaFileManager fileManager = compiler.getStandardFileManager( null, null, null );
Iterable<? extends JavaFileObject> javaSource = fileManager.getJavaFileObjectsFromFiles( sourceFileList );
CompilationTask task = compiler.getTask(null, fileManager, null, null, null, javaSource);
task.call(); // compile .java file into .class file
How can I run a compiled .class file and capture its output within my code?
回答1:
Once it's compiled, you will need to load the Class
object and then invoke the main(String[])
method. To capture the stdout, you will need to use System.setOut
.
private String invokeClass(String className) throws URISyntaxException, IOException, ReflectiveOperationException {
Class<?> clazz = Class.forName(className);
// Alternatively, you can load the new class with a new Classloader, if you don't want to pollute the current Classloader
// Class<?> clazz = new URLClassLoader(new URL[]{getClass().getClassLoader().getResource("").toURI().toURL()}, getClass().getClassLoader()).loadClass(className);
Method main = clazz.getDeclaredMethod("main", String[].class);
try ( ByteArrayOutputStream out = new ByteArrayOutputStream();
PrintStream ps = new PrintStream(out)) {
System.setOut(ps);
main.invoke(main, new Object[]{new String[0]});
return out.toString();
}
finally {
// Reset to the console
System.setOut(new PrintStream(new FileOutputStream(FileDescriptor.out)));
}
}
来源:https://stackoverflow.com/questions/30430056/running-a-compiled-java-class-file-from-within-java-code-and-capturing-output