Виконайте ще одну банку в програмі Java


115

Я написав кілька простих додатків Java, названих як A.jar, B.jar.

Тепер я хочу написати Java-програму GUI, щоб користувач міг натиснути кнопку A, щоб виконати A.jar, і кнопку B, щоб виконати B.jar.

Також я хочу вивести детальну інформацію про час роботи в моїй програмі GUI.

Будь-яка пропозиція?


31
Не впевнений, чому це було проголосовано. Поясніть йому, чому його припущення можуть бути помилковими, але не спростовуйте це питання.
— Вільям Брендель

-1 основна термінологія Java використовується не правильно, а питання дуже розпливчасте і залишає багато для другого здогаду. Подумайте переформулювати своє запитання з додатковими подробицями або спочатку прочитайте про Java classpath та інші основи.
— топчеф

21
@grigory: Подивіться, саме про це ви мали б запитати в першу чергу, а не зволікати відразу. Відхилення, навіть не запитуючи більше інформації, не приносить користі ...
— Вільям Брендель

4
@William, вибачте за натискання кнопки на кілька секунд пізніше, ніж ви. Я залишаю за собою право проголосувати проти подальших коментарів. Розчаровувати питання, задані без основної підготовки та / або зусиль, щоб зрозуміти чи представити проблему, неприємно. Голосування - це як підказка в ресторані: ви даєте більше або менше, ніж стандартні 12%, залежно від якості обслуговування. Тож давайте погодимось тут не погоджуватися.
— топчеф

1
@topchef Я запізнююсь на це 11 років, але ти кажеш, що "шкода бачити запитання без базової підготовки ...". Тоді допоможіть виправити це. Поясніть, чому ви відмовились. Інакше ти зовсім не допомагаєш проблемі.
— tylerr147

Відповіді:


63

Якщо я правильно розумію, здається, ви хочете запустити банки в окремий процес, що знаходиться всередині вашої програми GUI для Java.

Для цього ви можете скористатися:

// Run a java app in a separate system process
Process proc = Runtime.getRuntime().exec("java -jar A.jar");
// Then retreive the process output
InputStream in = proc.getInputStream();
InputStream err = proc.getErrorStream();

Завжди хороша практика буферування результатів процесу.


21
Це рішення портативне?
— Pacerier

3
Дякую. Я спробував exec () func з 3 параметрами, включаючи параметр "dir", і він не працює. Лише з одним нам потрібно лише помістити 3 файли .jar на те саме місце
— Duc Tran

Чи знаєте ви, як отримати Runtimeоб’єкт програми Java?
— stommestack

Чи можемо ми використовувати більш портативну версію, використовуючи ProcessBuilder?
— Ананд Рокз

Не вдається запустити програму "java": помилка CreateProcess = 2, система не може знайти вказаний файл. Отримання помилки
— Джентльмен

27

.jar не виконується. Миттєві класи або зателефонуйте до будь-якого статичного методу.

EDIT: Додайте запис основного класу під час створення JAR.

> p.mf (вміст p.mf)

Основний клас: pk.Test

>Test.java

package pk;
public class Test{
  public static void main(String []args){
    System.out.println("Hello from Test");
  }
}

Використовуйте клас Process і його методи,

public class Exec
{
   public static void main(String []args) throws Exception
    {
        Process ps=Runtime.getRuntime().exec(new String[]{"java","-jar","A.jar"});
        ps.waitFor();
        java.io.InputStream is=ps.getInputStream();
        byte b[]=new byte[is.available()];
        is.read(b,0,b.length);
        System.out.println(new String(b));
    }
}

1
Я думаю, що ідея полягає в тому, що, якщо ви отримаєте доступ до jar, як ви додасте його до classpath, щоб завантажити з нього класи.
— Jherico

1
Зауважте: він працює лише тому, що у вашому PATH є контейнер для Java, це не стосується встановлення Windows за замовчуванням
— poussma

@AVD: де слід зберігати файл A.jar?
— logan

1
@logan - у каталозі, де ви завантажуєте програму.
— адатапост

Чи створить такий підхід новий процес СВМ чи використає існуючий?
— RahulDeep Attri

17

Сподіваюсь, це допомагає:

public class JarExecutor {

private BufferedReader error;
private BufferedReader op;
private int exitVal;

public void executeJar(String jarFilePath, List<String> args) throws JarExecutorException {
    // Create run arguments for the

    final List<String> actualArgs = new ArrayList<String>();
    actualArgs.add(0, "java");
    actualArgs.add(1, "-jar");
    actualArgs.add(2, jarFilePath);
    actualArgs.addAll(args);
    try {
        final Runtime re = Runtime.getRuntime();
        //final Process command = re.exec(cmdString, args.toArray(new String[0]));
        final Process command = re.exec(actualArgs.toArray(new String[0]));
        this.error = new BufferedReader(new InputStreamReader(command.getErrorStream()));
        this.op = new BufferedReader(new InputStreamReader(command.getInputStream()));
        // Wait for the application to Finish
        command.waitFor();
        this.exitVal = command.exitValue();
        if (this.exitVal != 0) {
            throw new IOException("Failed to execure jar, " + this.getExecutionLog());
        }

    } catch (final IOException | InterruptedException e) {
        throw new JarExecutorException(e);
    }
}

public String getExecutionLog() {
    String error = "";
    String line;
    try {
        while((line = this.error.readLine()) != null) {
            error = error + "\n" + line;
        }
    } catch (final IOException e) {
    }
    String output = "";
    try {
        while((line = this.op.readLine()) != null) {
            output = output + "\n" + line;
        }
    } catch (final IOException e) {
    }
    try {
        this.error.close();
        this.op.close();
    } catch (final IOException e) {
    }
    return "exitVal: " + this.exitVal + ", error: " + error + ", output: " + output;
}
}

0

Якщо jar знаходиться на вашому classpath, і ви знаєте його Main class, ви можете просто викликати основний клас. Використовуючи DITA-OT як приклад:

import org.dita.dost.invoker.CommandLineInvoker;
....
CommandLineInvoker.main('-f', 'html5', '-i', 'samples/sequence.ditamap', '-o', 'test')

Зауважте, що це змусить підлеглу банку розділити простір пам’яті та класний шлях із вашою баночкою з усім потенціалом для перешкод, які можуть спричинити. Якщо ви не хочете, щоб цей матеріал забруднився, у вас є інші варіанти, як було сказано вище, а саме:

  • створіть новий ClassLoader з баночкою в ньому. Це більш безпечно; ви можете принаймні виділити знання нового банку до основного завантажувача, якщо ви архітектуруєте речі з тими знаннями, які ви будете використовувати чужих банок. Це ми робимо в своєму магазині для нашої системи плагінів; основне додаток - це крихітна оболонка із заводом ClassLoader, копія API та знання, що реальний додаток - це перший плагін, для якого він повинен створити ClassLoader. Плагіни - це пара банок - інтерфейс та реалізація -, які поєднуються між собою. Усі ClassLoaders поділяють всі інтерфейси, тоді як кожен ClassLoader має лише знання про власну реалізацію. Стек трохи складний, але він проходить всі тести і працює чудово.
  • використання Runtime.getRuntime.exec(...)(який повністю ізолює банку, але має нормальне значення "знайти додаток", "уникнути своїх рядків праворуч", "WTF-орієнтований на платформу" та "OMG System Threads" підводні камені запущених системних команд.

0

Далі працює, запускаючи банку з пакетного файлу, якщо програма працює як окрема:

public static void startExtJarProgram(){
        String extJar = Paths.get("C:\\absolute\\path\\to\\batchfile.bat").toString();
        ProcessBuilder processBuilder = new ProcessBuilder(extJar);
        processBuilder.redirectError(new File(Paths.get("C:\\path\\to\\JavaProcessOutput\\extJar_out_put.txt").toString()));
        processBuilder.redirectInput();
        try {
           final Process process = processBuilder.start();
            try {
                final int exitStatus = process.waitFor();
                if(exitStatus==0){
                    System.out.println("External Jar Started Successfully.");
                    System.exit(0); //or whatever suits 
                }else{
                    System.out.println("There was an error starting external Jar. Perhaps path issues. Use exit code "+exitStatus+" for details.");
                    System.out.println("Check also C:\\path\\to\\JavaProcessOutput\\extJar_out_put.txt file for additional details.");
                    System.exit(1);//whatever
                }
            } catch (InterruptedException ex) {
                System.out.println("InterruptedException: "+ex.getMessage());
            }
        } catch (IOException ex) {
            System.out.println("IOException. Faild to start process. Reason: "+ex.getMessage());
        }
        System.out.println("Process Terminated.");
        System.exit(0);
    }

У batchfile.bat тоді можна сказати:

@echo off
start /min C:\path\to\jarprogram.jar

-3

Якщо ви - java 1.6, також можна зробити наступне:

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

public class CompilerExample {

    public static void main(String[] args) {
        String fileToCompile = "/Users/rupas/VolatileExample.java";

        JavaCompiler compiler = ToolProvider.getSystemJavaCompiler();

        int compilationResult = compiler.run(null, null, null, fileToCompile);

        if (compilationResult == 0) {
            System.out.println("Compilation is successful");
        } else {
            System.out.println("Compilation Failed");
        }
    }
}

4
Я не думаю, що це відповідає на питання ОП
— Шрі Харша Чілакапаті
Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.