1

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?

wesleyy
  • 2,575
  • 9
  • 34
  • 54

2 Answers2

2

Try to set to java process you're launching the correct working directory and then set the related classpath.

This should help.

Update

I suggest to use the method Runtime.getRuntime().exec(String command, String[] envp, File dir).

Last parameter dir is the process working directory.

freedev
  • 25,946
  • 8
  • 108
  • 125
1

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
Neeraj Jain
  • 7,643
  • 6
  • 34
  • 62
  • But you have to give it the path to the program, right? What if the program is not in the project root, but for example in "./data/Main.java"? How should the run command be then? – wesleyy May 03 '17 at 10:33
  • Yes you have to but then you need to change your getProgramName() method to return you the correct class name – Neeraj Jain May 03 '17 at 10:35
  • What happens if the compiled file is ie in "./data/Main.class"? How do you execute the program then? It should make some difference, no? – wesleyy May 03 '17 at 10:37
  • In that case, you need to use `-cp` flag to provide the correct class path and then the class name `java -cp ../somepath../ Main` – Neeraj Jain May 03 '17 at 10:40
  • whosoever downvoted, do comment so that I can improve the answer or can remove it. if the answer is not appropriate. But do care to comment – Neeraj Jain May 07 '17 at 15:19