How to compile and run inside a java program

I want to open a Java GUI using another Java program.
It compiled successfully, but it cannot run. It says "unable to load main class". Here is my code:

import javax.tools.JavaCompiler;
import javax.tools.ToolProvider;


public class Test {

  public static void main(String[] args) {
    try {
        JavaCompiler jc = ToolProvider.getSystemJavaCompiler();
        jc.run(System.in, System.out, System.err, "src/HelloWorld.java");

        // I think this line has the error
        Runtime.getRuntime().exec("cmd.exe /c start java src/HelloWorld");
    } catch (Exception e) {
      e.printStackTrace();
    }
  }
}

      

HelloWorld class:

import javax.swing.JFrame;
public class HelloWorld {
public static void main(String[] args) {
    JFrame frame = new JFrame();
    frame.setSize(100, 500);
    frame.setVisible(true);
    frame.setResizable(false);
    frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
}
}

      

+1


source to share


1 answer


There are many possible places where the code can fail, for example, it may not compile for some reason; java

may not be in the OS search path; the command java

may fail because the parameter src/HelloWorld

looks wrong.

I believe your command should be more like java -cp ./src HelloWorld

or should be executed from a directory context src

...

You really need to make every effort to diagnose potential problems, such as DiagnosticCollector

for JavaCompiler

reading and processes InputStream

andErrorStream

Building on yours HelloWorld.java

and this previous answer , I was able to create this example that can compile and run your class successfully ...



import java.io.File;
import java.io.IOException;
import java.io.InputStream;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;
import java.util.logging.Level;
import java.util.logging.Logger;
import javax.tools.Diagnostic;
import javax.tools.DiagnosticCollector;
import javax.tools.JavaCompiler;
import javax.tools.JavaFileObject;
import javax.tools.StandardJavaFileManager;
import javax.tools.ToolProvider;

public class TestCompile {

    public static void main(String[] args) {
        StringBuilder sb = new StringBuilder(64);

        try {
            DiagnosticCollector<JavaFileObject> diagnostics = new DiagnosticCollector<>();
            JavaCompiler compiler = ToolProvider.getSystemJavaCompiler();
            try (StandardJavaFileManager fileManager = compiler.getStandardFileManager(diagnostics, null, null)) {
                // >>>> Compiler Stage
                // 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<>();
                optionList.add("-classpath");
                optionList.add(System.getProperty("java.class.path"));

                Iterable<? extends JavaFileObject> compilationUnit
                                = fileManager.getJavaFileObjectsFromFiles(Arrays.asList(new File("src/HelloWorld.java")));
                JavaCompiler.CompilationTask task = compiler.getTask(
                                null,
                                fileManager,
                                diagnostics,
                                optionList,
                                null,
                                compilationUnit);
                if (task.call()) {
                    // <<<< Compiler Stage
                    // >>>> Run stage...
                    ProcessBuilder pb = new ProcessBuilder("java", "-cp", "./src", "HelloWorld");
                    pb.redirectError();
                    Process p = pb.start();

                    InputStreamConsumer.consume(p.getInputStream());

                    p.waitFor();
                    // <<<< Run Stage
                } else {
                    for (Diagnostic<? extends JavaFileObject> diagnostic : diagnostics.getDiagnostics()) {
                        System.out.format("Error on line %d in %s%n",
                                        diagnostic.getLineNumber(),
                                        diagnostic.getSource().toUri());
                    }
                }
            } catch (InterruptedException ex) {
                Logger.getLogger(TestCompile.class.getName()).log(Level.SEVERE, null, ex);
            }
        } catch (IOException exp) {
            exp.printStackTrace();
        }
    }

    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();
            }
        }

    }
}

      

As an alternative to using ProcessBuilder pb = new ProcessBuilder("java", "-cp", "./src", "HelloWorld");

, you can actually use ...

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

      

Will start a process java

in a directory contextsrc

+3


source







All Articles