3

I need to write a code that could help me to get the output of a program.

I have in that Java file MainClass.java that I am compiling, a simple code that prints "OK".

How could I return this output and even if there is error, I need to take it as well.

This is my code that compile and create a .class file.

File sourceFile = new File("C:\\Projet_Interne\\webProject\\NewFolder\\MainClass.java"); JavaCompiler compiler = ToolProvider.getSystemJavaCompiler(); int compilationResult = compiler.run(null, null, null,sourceFile.getPath()); int result = compiler.run(System.in,System.out,System.err,sourceFile.getPath()); System.out.println("Compile result code = " + result); if(compilationResult == 0){ System.out.println("Compilation is successful"); }else{ System.out.println("Compilation Failed"); } StandardJavaFileManager stdFileManager = compiler.getStandardFileManager(null, Locale.getDefault(), null); stdFileManager.setLocation(StandardLocation.CLASS_OUTPUT, Arrays.asList(new File("C:\\Projet_Interne\\webProject\\NewFolder"))); 
2
  • You need to run the resulting code, either use a ClassLoader or ProcessBuilder, for example and example Commented Aug 7, 2014 at 8:14
  • when you compile a source code it prints on the console if errors happened. if you get the final class file, the program is ready to run Commented Aug 7, 2014 at 8:16

2 Answers 2

1

You could use the DiagnosticCollector, which will allow you to collect diagnostic information about the compilation process, you can find more details from the JavaDocs

For example...

File helloWorldJava = new File(...); DiagnosticCollector<JavaFileObject> diagnostics = new DiagnosticCollector<JavaFileObject>(); JavaCompiler compiler = ToolProvider.getSystemJavaCompiler(); StandardJavaFileManager fileManager = compiler.getStandardFileManager(diagnostics, null, null); // This sets up the class path that the compiler will use. // I've added the .jar file that contains the DoStuff interface within in it... List<String> optionList = new ArrayList<String>(); optionList.add("-classpath"); optionList.add(System.getProperty("java.class.path")); Iterable<? extends JavaFileObject> compilationUnit = fileManager.getJavaFileObjectsFromFiles(Arrays.asList(helloWorldJava)); JavaCompiler.CompilationTask task = compiler.getTask( null, fileManager, diagnostics, optionList, null, compilationUnit); if (task.call()) { System.out.println("Yipe"); } else { // Opps compile failed... for (Diagnostic<? extends JavaFileObject> diagnostic : diagnostics.getDiagnostics()) { System.out.format("Error on line %d in %s%n", diagnostic.getLineNumber(), diagnostic.getSource().toUri()); } } fileManager.close(); 

Once compiled, you have two choices, you can either use a custom class loader to load the class and execute it, which will use your current stdout...

// Create a new custom class loader, pointing to the directory that contains the compiled // classes, this should point to the top of the package structure! URLClassLoader classLoader = new URLClassLoader(new URL[]{new File("./").toURI().toURL()}); // Load the class from the classloader by name.... Class<?> loadedClass = classLoader.loadClass("testcompile.HelloWorld"); // Create a new instance... Object obj = loadedClass.newInstance(); // Santity check if (obj instanceof DoStuff) { // Cast to the DoStuff interface DoStuff stuffToDo = (DoStuff)obj; // Run it baby stuffToDo.doStuff(); } 

Or use a ProcessBuilder to execute another Java process...

ProcessBuilder pb = new ProcessBuilder("java", "HelloWorld"); pb.directory(new File("src")); pb.redirectError(); Process p = pb.start(); InputStreamConsumer.consume(p.getInputStream()); p.waitFor(); 

For reference, the InputStreamConsumer....

public static class InputStreamConsumer implements Runnable { private InputStream is; public InputStreamConsumer(InputStream is) { this.is = is; } public InputStream getInputStream() { return is; } public static void consume(InputStream is) { InputStreamConsumer consumer = new InputStreamConsumer(is); Thread t = new Thread(consumer); t.start(); } @Override public void run() { InputStream is = getInputStream(); int in = -1; try { while ((in = is.read()) != -1) { System.out.print((char)in); } } catch (IOException exp) { exp.printStackTrace(); } } } 

This is outlined in more detail in:

Sign up to request clarification or add additional context in comments.

2 Comments

thx for ur answer even its a long process but it do the job :)
@Neeldz Lots of options :P
1

The run method can use streams to handle input and output:

int run(InputStream in, OutputStream out, OutputStream err, String... arguments) 

Use an OutputStream for out and read from it when run is finished.

2 Comments

Which seems to be what the OP is doing ... int result = compiler.run(System.in,System.out,System.err,sourceFile.getPath());, or are they doing it wrong?
thx Tichodroma for ur reply i did already use this method as below but that function only return an int value i need to get what the compiled class has return wish in this case is "OK".int result = compiler.run(System.in,System.out,System.err,sourceFile.getPath());

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.