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


114

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

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

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

어떠한 제안?


31
이것이 왜 거절되었는지 확실하지 않습니다. 그의 가정이 잘못된 이유를 그에게 설명하되 질문에 대해 찬성하지 마십시오.
William Brendel

-1 기본 Java 용어가 올바르게 사용되지 않고 질문이 매우 모호하며 두 번째 추측에 많은 것을 남깁니다. 더 자세한 내용으로 질문을 다시 작성하거나 Java 클래스 경로 및 기타 기본 사항에 대해 먼저 읽으십시오.
topchef

21
@grigory : 바로 다운 투표하는 대신 처음부터 요청 했어야하는 내용입니다. 더 많은 정보를 요구하지 않고 반대 투표는 아무 소용이 없습니다 ...
William Brendel

4
@William, 당신보다 몇 초 늦게 버튼을 눌러서 죄송합니다. 나는 후속 의견에 대해 투표 할 권리가 있습니다. 기본적인 준비 및 / 또는 문제를 이해하거나 제시하려는 노력없이 질문을 보는 것은 실망 스럽습니다. 투표는 제게 식당의 팁과 같습니다. 서비스 품질에 따라 표준 12 % 이하를 제공합니다. 그러니 여기에 동의하지 않는 것에 동의합시다.
topchef

1
@topchef 저는 11 년이 늦었지만 "기본적인 준비없이 질문을 보니 답답 해요 ..." 그런 다음 문제를 해결하십시오. 반대표를 던진 이유 를 설명 하세요. 그렇지 않으면 문제를 전혀 돕지 않습니다.
tylerr147

답변:


63

내가 올바르게 이해하면 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();

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


21
이 솔루션은 휴대용입니까?
Pacerier 2012

3
감사. "dir"매개 변수를 포함하여 3 개의 매개 변수로 exec () func를 시도했지만 작동하지 않습니다. 하나, 우리는 단지 3 개 개의 파일이 같은 장소에 .JAR 둘 필요
둑 트란

Runtime해당 자바 애플리케이션 의 객체 를 얻는 방법을 알고 있습니까?
stommestack 2014 년

ProcessBuilder를 사용하여 더 이식 가능한 버전을 사용할 수 있습니까?
Anand Rockzz 2014 년

"java"프로그램을 실행할 수 없음 : CreateProcess error = 2, 시스템이 지정된 파일을 찾을 수 없습니다. 이 오류가 발생합니다.
Gentleman

27

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

1
나는 아이디어가 항아리에 대한 액세스 권한이 주어지면 클래스를로드하기 위해 클래스 경로에 어떻게 추가합니까?
Jherico

1
참고 : 당신이 당신의 PATH에 자바 빈을 가지고 있기 때문에 단지 작동이 기본 Windows 설치의 경우에는 해당되지 않습니다
poussma

@AVD : A.jar 파일은 어디에 보관해야합니까?
logan

1
@logan-프로그램을로드하는 디렉토리.
adatapost 2014 년

이 접근 방식은 새로운 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가 클래스 경로에 있고 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 시스템 스레드") 시스템 명령 실행의 함정이 있습니다.

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
나는이 대답에게 OP의 질문 생각하지 않는다
스리랑카 Harsha에 Chilakapati
당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.