Как скомпилировать и запустить программу Java из другой программы Java

Думали ли вы когда-либо о возможности компиляции и запуска программы на Java из другой программы на Java? Мы можем использовать Runtime.exec(String cmd) для выполнения команд в базовой операционной системе. Мы будем использовать тот же подход для компиляции и запуска программы на Java из другой программы на Java.

Компиляция и запуск программы на Java из другой программы на Java

Давайте напишем простую программу на Java, которая будет скомпилирована и запущена из другой программы на Java.

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

    }

}

Вот другая программа, в которой я компилирую и запускаю класс Test.

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

}

Обратите внимание на разницу в командах javac и java. Нам нужно сделать это, потому что рабочий каталог Eclipse – это корневой каталог проекта, но мой каталог исходных классов – это src. Когда я запускаю вышеуказанную программу из Eclipse, происходит следующий вывод.

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

Вот вывод, когда я запускаю ту же программу из командной строки, рабочий каталог – корневой каталог проекта.

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$ 

Программа выше будет работать нормально в системах Unix, но не будет работать в системах Windows из-за различий в разделителях файлов. Чтобы сделать ее платформонезависимой, мы можем передавать команды в качестве аргумента в функцию main. Основная функция будет выглядеть следующим образом:

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

Мы также можем использовать File.separator для создания команд способом, не зависящим от платформы. Это свойство также можно получить с помощью метода System.getProperty и System.getProperty("file.separator"). Программу выше можно изменить следующим образом для создания кода, не зависящего от системы:

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");

Вы получите тот же вывод, что и ранее. Вот и все, что касается использования метода exec класса Runtime для компиляции и запуска программы на Java из другой программы на Java. Методы printLines() и runProcess() взяты из этого поста.

Source:
https://www.digitalocean.com/community/tutorials/compile-run-java-program-another-java-program