Execute outro jar em um programa Java


115

Eu escrevi vários aplicativos Java simples chamados A.jar, B.jar.

Agora, eu quero escrever um programa GUI java para que o usuário possa pressionar o botão A para executar A.jar e o botão B para executar B.jar.

Também quero gerar os detalhes do processo de tempo de execução no meu programa GUI.

Alguma sugestão?


31
Não sei por que isso foi rejeitado. Explique a ele por que suas suposições podem estar erradas, mas não vote contra a pergunta.
William Brendel

-1 terminologia Java básica não é usada corretamente e a pergunta é muito vaga e deixa muito para adivinhar. Considere reformular sua pergunta com mais detalhes ou simplesmente leia sobre o classpath Java e outros princípios básicos primeiro.
topchef

21
@grigory: Veja, isso é o que você deveria ter perguntado em primeiro lugar, em vez de downvoting imediatamente. Downvoting sem mesmo pedir mais informações não adianta nada ...
William Brendel

4
@William, desculpe por apertar o botão alguns segundos depois de você. Eu me reservo o direito de votar contra com comentários subsequentes. É frustrante ver perguntas feitas sem preparação básica e / ou esforço para entender ou apresentar o problema. Votar é como uma gorjeta em um restaurante para mim: você dá mais ou menos 12% do padrão dependendo da qualidade do serviço. Então, vamos concordar em discordar aqui.
topchef

1
@topchef Estou 11 anos atrasado para isso, mas você diz "É frustrante ver perguntas feitas sem uma preparação básica ...". Então ajude a consertar. Explique por que você votou negativamente. Do contrário, você não está ajudando em nada o problema.
tylerr147

Respostas:


63

Se bem entendi, parece que você deseja executar os jars em um processo separado de dentro de seu aplicativo GUI java.

Para fazer isso, você pode usar:

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

É sempre uma boa prática armazenar em buffer a saída do processo.


21
Esta solução é portátil?
Pacerier

3
obrigado. Eu tentei func exec () com 3 parâmetros, incluindo o parâmetro "dir" e não funciona. Com apenas um, só precisamos colocar os 3 arquivos .jar no mesmo lugar
Duc Tran

Você sabe como obter o Runtimeobjeto desse aplicativo java?
Stommestack

Podemos usar uma versão mais portátil, usando ProcessBuilder?
Anand Rockzz

Não é possível executar o programa "java": erro CreateProcess = 2, O sistema não pode encontrar o arquivo especificado. Obtendo este erro.
Cavalheiro de

27

.jar não é executável. Instancie classes ou faça chamadas para qualquer método estático.

EDIT: Adicionar entrada de classe principal ao criar um JAR.

> p.mf (conteúdo de p.mf)

Classe principal: pk.Test

>Test.java

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

Use a classe Process e seus métodos,

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
Acho que a ideia é dar acesso a um jar, como adicioná-lo ao classpath para carregar classes a partir dele.
Jherico

1
Nota: funciona apenas porque você tem o java bin em seu PATH, este não é o caso para a instalação padrão do Windows
poussma

@AVD: onde o arquivo A.jar deve ser mantido?
logan

1
@logan - Em um diretório onde você está carregando um programa.
adatapost

Essa abordagem criará um novo processo JVM ou usará o existente?
RahulDeep Attri

17

Espero que isto ajude:

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

Se o jar estiver em seu classpath e você souber sua classe Main, basta invocar a classe principal. Usando DITA-OT como exemplo:

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

Observe que isso fará com que o jar subordinado compartilhe espaço de memória e um caminho de classe com seu jar, com todo o potencial de interferência que pode causar. Se você não quiser que esse material seja poluído, você tem outras opções, conforme mencionado acima - a saber:

  • crie um novo ClassLoader com o jar nele. Isso é mais seguro; você pode, pelo menos, isolar o conhecimento do novo jar para um carregador de classe central se você arquitetar coisas com o conhecimento de que usará jarros alienígenas. É o que fazemos em minha loja para nosso sistema de plug-ins; o aplicativo principal é um pequeno shell com uma fábrica ClassLoader, uma cópia da API e o conhecimento de que o aplicativo real é o primeiro plug-in para o qual ele deve construir um ClassLoader. Os plug-ins são um par de jars - interface e implementação - que são compactados juntos. Todos os ClassLoaders compartilham todas as interfaces, enquanto cada ClassLoader tem conhecimento apenas de sua própria implementação. A pilha é um pouco complexa, mas passa em todos os testes e funciona perfeitamente.
  • use Runtime.getRuntime.exec(...)(que isola totalmente o jar, mas tem as armadilhas normais de "localizar o aplicativo", "escapar das strings corretamente", "WTF específico da plataforma" e "OMG System Threads" na execução de comandos do sistema.

0

O seguinte funciona iniciando o jar com um arquivo em lote, caso o programa seja executado como um autônomo:

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

No batchfile.bat então podemos dizer:

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

-3

Se você for java 1.6, o seguinte também pode ser feito:

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
Não acho que isso responda à pergunta do OP
Sri Harsha Chilakapati
Ao utilizar nosso site, você reconhece que leu e compreendeu nossa Política de Cookies e nossa Política de Privacidade.
Licensed under cc by-sa 3.0 with attribution required.