Выполнить другую банку в программе Java


115

Я написал несколько простых java-приложений с именами A.jar, B.jar.

Теперь я хочу написать Java-программу с графическим интерфейсом, чтобы пользователь мог нажать кнопку A для выполнения A.jar и кнопку B для выполнения B.jar.

Также я хочу вывести детали процесса выполнения в моей программе с графическим интерфейсом.

Любое предложение?


31
Не уверен, почему это было отклонено. Объясните ему, почему его предположения могут быть ошибочными, но не ставьте вопрос против.
Уильям Брендель,

-1 базовая терминология Java используется неправильно, вопрос очень расплывчатый и оставляет много сомнений. Попробуйте перефразировать свой вопрос с более подробной информацией или просто сначала прочтите о пути к классам Java и других основах.
topchef

21
@grigory: Видите ли, это то, что вы должны были спросить в первую очередь, вместо того, чтобы сразу же голосовать против. Голосование против, даже не запрашивая дополнительной информации, не приносит никакой пользы ...
Уильям Брендель,

4
@ Уильям, извини, что нажал кнопку на несколько секунд позже, чем ты. Я оставляю за собой право проголосовать против с последующим комментарием. Очень неприятно видеть вопросы, которые задают без базовой подготовки и / или усилий, чтобы понять или изложить проблему. Голосование для меня как чаевые в ресторане: вы отдаете больше или меньше стандартных 12% в зависимости от качества обслуживания. Так что давайте соглашаться не соглашаться здесь.
topchef

1
@topchef Я опаздываю на 11 лет, но вы говорите: «Прискорбно видеть вопросы, которые задают без базовой подготовки ...». Тогда помогите исправить. Объясните, почему вы проголосовали против. В противном случае вы вообще не поможете проблеме.
tylerr147

Ответы:


63

Если я правильно понимаю, похоже, вы хотите запускать jar-файлы в отдельном процессе из вашего приложения с графическим интерфейсом 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 () с 3 параметрами, включая параметр «dir», и это не работает. Имея только один, нам нужно только поместить 3 файла .jar в одно и то же место
Duc Tran

Вы знаете, как получить Runtimeобъект этого Java-приложения?
Stommestack

Можно ли использовать более переносимую версию с помощью ProcessBuilder?
Anand Rockzz

Не удается запустить программу «java»: ошибка CreateProcess = 2, система не может найти указанный файл. Получение этой ошибки.
Джентльмен

27

.jar не исполняемый. Создайте экземпляры классов или вызовите любой статический метод.

РЕДАКТИРОВАТЬ: добавить запись основного класса при создании 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");
  }
}

Используйте класс процесса и его методы,

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
Я думаю, идея состоит в том, что при доступе к банке, как вы добавляете его в путь к классам, чтобы загружать классы из него.
Jherico

1
Примечание: это работает только потому, что у вас есть java bin в вашем PATH, это не относится к установке Windows по умолчанию
poussma

@AVD: где хранить файл A.jar?
logan

1
@logan - в каталоге, куда вы загружаете программу.
adatapost

Будет ли этот подход создавать новый процесс JVM или использовать существующий?
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 находится в вашем пути к классам, и вы знаете его основной класс, вы можете просто вызвать основной класс. На примере DITA-OT:

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

Обратите внимание, что это приведет к тому, что подчиненный jar будет совместно использовать пространство памяти и путь к классам с вашим jar, со всеми возможными помехами, которые могут вызвать. Если вы не хотите, чтобы этот материал был загрязнен, у вас есть другие варианты, как упоминалось выше, а именно:

  • создайте новый ClassLoader с jar в нем. Это более безопасно; вы можете по крайней мере изолировать знания нового jar-файла от основного загрузчика классов, если вы проектируете вещи, зная, что вы будете использовать инопланетные jar-файлы. Это то, что мы делаем в моем магазине для нашей системы плагинов; основное приложение - это крошечная оболочка с фабрикой ClassLoader, копией API и знанием того, что реальное приложение - это первый плагин, для которого оно должно создать ClassLoader. Плагины - это пара jar-файлов - интерфейс и реализация, - которые скреплены вместе. Все загрузчики классов совместно используют все интерфейсы, в то время как каждый загрузчик классов знает только о своей собственной реализации. Стек немного сложный, но он проходит все тесты и прекрасно работает.
  • use Runtime.getRuntime.exec(...)(который полностью изолирует jar-файл, но имеет обычные ошибки запуска системных команд «найти приложение», «экранировать строки правильно», «специфичный для платформы WTF» и «OMG System Threads».

0

Следующее работает, запустив jar с помощью командного файла, если программа работает как отдельная:

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.