Search code examples
javajavac

Compile and run a Java program from another Java program


I am writing a program that takes the path to the input ".java" file with a main method. The program should then compile that file, and run it.

Let's say that the program I am trying to compile and run looks like this:

Main.java

public class Main {

    public static void main(String[] args) {
        System.out.println("Hello, world!");
    }
}

The program that performs compilation and tries to run it:

Evaluator.java

    /**
     * Matches any .java file.
     */
    private static final PathMatcher matcher = FileSystems.getDefault().getPathMatcher("glob:**.java");

    private static String path;

    /**
     * Program entry point. Obtains the path to the .java file as a command line argument.
     * 
     * @param args One argument from the command line: path to the .java file.
     * @throws Exception 
     */
    public static void main(String[] args) throws Exception {
        if (args.length != 1) {
            throw new IllegalArgumentException(
                    "Expected exactly one argument from the command line.");
        }

        if (!matcher.matches(Paths.get(args[0]))) {
            throw new IllegalArgumentException(
                    String.format("File %s is not a valid java file.", args[0]));
        }

        // path is in a valid format
        path = args[0];

        // compile a program
        compile();

        // run a program
        run();
    }

    /**
     * Compiles a program.
     * 
     * @throws Exception
     */
    private static void compile() throws Exception {
        System.out.println("Compiling the program ...");

        Process p = Runtime.getRuntime().exec("javac " + path);
        output("Std.In", p.getInputStream());
        output("Std.Out", p.getErrorStream());
        p.waitFor();

        System.out.println("Program successfully compiled!\n");
    }

    /**
     * Runs a program.
     * 
     * @throws Exception
     */
    private static void run() throws Exception {
        System.out.println("Executing the program ...");

        Process p = Runtime.getRuntime().exec("java " + getProgramName(path));
        output("Std.In", p.getInputStream());
        output("Std.Out", p.getErrorStream());
        p.waitFor();

        System.out.println("Program finished!");
    }

    private static void output(String stream, InputStream in) throws IOException {      
        BufferedReader reader = new BufferedReader(new InputStreamReader(in, CS));

        for (String line = reader.readLine(); line != null; line = reader.readLine()) {
            System.out.println(String.format("%s: %s", stream, line));
        }
    }

    private static String getProgramName(String path) {
        return path.replace(".java", "");
    }
}

My "Main.java" file is located in the project root. I am running the program with a command line argument "./Main.java". Doing so, compiles the program correctly and yields a new file "Main.class". However, the run method outputs as follows:

Std.Out: Error: Could not find or load main class ..Main

What should be the problem here?


Solution

  • The Problem here is you are passing argument

    ./Main.java
    

    instead, you should pass Main.java as an argument else you need to change your getProgramName() method to return the Class name correctly.

    Which will let you compile the program perfectly with javac command but problem happens when you need to run the program because that command should be

    java Main
    

    whereas you are trying to execute

    java ./Main