Виконайте ще одну банку в програмі 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.