[java] Java 프로그램에서 다른 jar 실행

A.jar, B.jar라는 이름의 간단한 Java 응용 프로그램을 여러 개 작성했습니다.

이제 사용자가 버튼 A를 눌러 A.jar을 실행하고 버튼 B를 눌러 B.jar를 실행할 수 있도록 GUI Java 프로그램을 작성하고 싶습니다.

또한 GUI 프로그램에서 런타임 프로세스 세부 정보를 출력하고 싶습니다.

어떠한 제안?



답변

내가 올바르게 이해하면 Java GUI 응용 프로그램 내부에서 별도의 프로세스에서 jar를 실행하려는 것으로 보입니다.

이렇게하려면 다음을 사용할 수 있습니다.

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

항상 프로세스의 출력을 버퍼링하는 것이 좋습니다.


답변

.jar는 실행 가능하지 않습니다. 클래스를 인스턴스화하거나 정적 메서드를 호출합니다.

편집 : JAR을 만드는 동안 Main-Class 항목을 추가합니다.

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


답변

도움이 되었기를 바랍니다:

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


답변

jar가 클래스 경로에 있고 Main 클래스를 알고 있다면 메인 클래스를 호출 할 수 있습니다. DITA-OT를 예로 사용 :

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

이렇게하면 하위 jar가 메모리 공간과 jar와 클래스 경로를 공유하게되며, 간섭을 일으킬 수있는 모든 가능성이 있습니다. 그 물건을 오염시키지 않으려면 위에서 언급했듯이 다른 옵션이 있습니다.

  • 항아리가있는 새 ClassLoader를 만듭니다. 이것은 더 안전합니다. 외계인 항아리를 사용할 것이라는 지식으로 무언가를 설계한다면 최소한 새로운 항아리의 지식을 핵심 클래스 로더에 격리시킬 수 있습니다. 플러그인 시스템을 위해 내 가게에서하는 일입니다. 주 응용 프로그램은 ClassLoader 팩토리, API 사본 및 실제 응용 프로그램이 ClassLoader를 빌드해야하는 첫 번째 플러그인이라는 지식이있는 작은 셸입니다. 플러그인은 한 쌍의 jar (인터페이스 및 구현)로 압축되어 있습니다. ClassLoader는 모두 모든 인터페이스를 공유하지만 각 ClassLoader는 자체 구현에 대한 지식 만 가지고 있습니다. 스택은 약간 복잡하지만 모든 테스트를 통과하고 아름답게 작동합니다.
  • 사용 Runtime.getRuntime.exec(...)(단지를 완전히 분리하지만 정상적인 “응용 프로그램 찾기”, “문자열 오른쪽 이스케이프”, “플랫폼 별 WTF”및 “OMG 시스템 스레드”) 시스템 명령 실행의 함정이 있습니다.

답변

다음은 프로그램이 독립형으로 실행되는 경우 배치 파일로 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


답변

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


답변