Have you ever thought if it’s possible to compile and run a java program from another java program? We can use Runtime.exec(String cmd)
to issue commands to the underlying operating system. We will use the same approach to compile and run a java program from another java program.
Let’s write a simple java program that will be compiled and run from another java program.
package com.journaldev.files;
public class Test {
public static void main(String[] args) {
System.out.println("Start");
for(String str : args){
System.out.println(str);
}
}
}
Here is the other program where I am compiling and running the Test class.
package com.journaldev.files;
import java.io.BufferedReader;
import java.io.InputStream;
import java.io.InputStreamReader;
public class CompileRunJavaProgram {
public static void main(String[] args) {
try {
runProcess("pwd");
System.out.println("**********");
runProcess("javac -cp src src/com/journaldev/files/Test.java");
System.out.println("**********");
runProcess("java -cp src com/journaldev/files/Test Hi Pankaj");
} catch (Exception e) {
e.printStackTrace();
}
}
private static void printLines(String cmd, InputStream ins) throws Exception {
String line = null;
BufferedReader in = new BufferedReader(
new InputStreamReader(ins));
while ((line = in.readLine()) != null) {
System.out.println(cmd + " " + line);
}
}
private static void runProcess(String command) throws Exception {
Process pro = Runtime.getRuntime().exec(command);
printLines(command + " stdout:", pro.getInputStream());
printLines(command + " stderr:", pro.getErrorStream());
pro.waitFor();
System.out.println(command + " exitValue() " + pro.exitValue());
}
}
Notice the difference in javac
and java
commands. We need to do this because Eclipse working directory is the project root directory but my classes source directory is src. When I run the above program from Eclipse, here is the output produced.
pwd stdout: /Users/pankaj/Documents/eclipse-workspace/JavaExceptions
pwd exitValue() 0
**********
Path Serapartor = /
javac -cp src src/com/journaldev/files/Test.java exitValue() 0
**********
java -cp src com/journaldev/files/Test Hi Pankaj stdout: Start
java -cp src com/journaldev/files/Test Hi Pankaj stdout: Hi
java -cp src com/journaldev/files/Test Hi Pankaj stdout: Pankaj
java -cp src com/journaldev/files/Test Hi Pankaj exitValue() 0
Here is the output when I run the same program from the command line, the working directory is the project root directory.
pankaj:~ pankaj$ cd /Users/pankaj/Documents/eclipse-workspace/JavaExceptions
pankaj:JavaExceptions pankaj$ javac -cp src src/com/journaldev/files/Test.java
pankaj:JavaExceptions pankaj$ javac -cp src src/com/journaldev/files/CompileRunJavaProgram.java
pankaj:JavaExceptions pankaj$ java -cp src com/journaldev/files/CompileRunJavaProgram
pwd stdout: /Users/pankaj/Documents/eclipse-workspace/JavaExceptions
pwd exitValue() 0
**********
javac -cp src src/com/journaldev/files/Test.java exitValue() 0
**********
java -cp src com/journaldev/files/Test Hi Pankaj stdout: Start
java -cp src com/journaldev/files/Test Hi Pankaj stdout: Hi
java -cp src com/journaldev/files/Test Hi Pankaj stdout: Pankaj
java -cp src com/journaldev/files/Test Hi Pankaj exitValue() 0
pankaj:JavaExceptions pankaj$
The above program will work fine in Unix systems but it will not work in Windows systems because Windows File separator is different from Unix file separators. To make sure it’s platform independent, we can pass commands as an argument to the main function. The main function will look like this:
public static void main(String[] args) {
try {
if(args.length < 2) throw new Exception("Mandatory Arguments missing");
runProcess(args[0]);
runProcess(args[1]);
} catch (Exception e) {
e.printStackTrace();
}
}
We can also use File.separator
to create the commands in platform independent way. We can also get this property from System getProperty method System.getProperty("file.separator")
. Above program can be changed like below for system independent code.
String separator = File.separator;
System.out.println("File Serapartor = "+separator);
separator = System.getProperty("file.separator");
System.out.println("File Serapartor = "+separator);
runProcess("javac -cp src src"+separator+"com"+separator+"journaldev"+separator+"files"+separator+"Test.java");
System.out.println("**********");
runProcess("java -cp src com"+separator+"journaldev"+separator+"files"+separator+"Test Hi Pankaj");
You will get the same output as above. That’s all for using Runtime exec method to compile and run a java program from another java program. The printLines() and runProcess() methods are taken from this post.
Thanks for learning with the DigitalOcean Community. Check out our offerings for compute, storage, networking, and managed databases.
While we believe that this content benefits our community, we have not yet thoroughly reviewed it. If you have any suggestions for improvements, please let us know by clicking the “report an issue“ button at the bottom of the tutorial.
The problem with this solution is, that the user needs to have java and javac in the PATH environment variable. A better way might be to use the JavaCompiler and ClassLoader classes.
- Anonymous
Your passion for open source gave me a boner. God bless you!
- Amina Tole
how can i run some external java file? its getting compile but showing error “Could not find or load main class Test” while running the file.
- yogita
how can I run program which is in another folder
- yogita
How can I provide input to the Test.java file if it asks for user input?
- Dendrowen
Appreciated…!
- Madhu
I get an error message that that ''Could not find or load main class Test".
- Abhimanyu Datta