Execute a JAR File From a Java Program

1. 소개

Java 프로젝트를 작업하는 동안, 외부 JAR (실행 가능한 JAR)를 Java 프로그램 내에서 별도의 프로세스로 실행하고 출력 결과를 확인해야 하는 상황을 만날 수 있습니다. 또는 외부 JAR에 있는 main 메서드가 있는 클래스 파일을 실행하고 싶을 수도 있습니다.

이 튜토리얼에서는 두 가지 시나리오를 처리하는 방법과 코드 예제를 살펴보겠습니다.

2. 실행 가능한 JAR 실행하기

실행 가능한 JAR는 Main-Class 속성이 설정된 매니페스트 파일을 포함하는 JAR 파일의 한 종류입니다. 이 속성은 가장 먼저 실행되어야 하는 클래스 파일(즉, main 메서드가 있는 클래스)을 가리킵니다.

이 JAR는 명령줄에서 java -jar 명령을 사용하여 실행할 수 있습니다. Java 프로그램 내에서 ProcessBuilder를 사용하여 유사한 결과를 얻을 수 있습니다.

아래 코드는 실행 가능한 JAR를 별도의 프로세스로 프로그래밍적으로 실행하고, 콘솔에서 출력 결과를 볼 수 있는 방법을 보여줍니다:

@Test
public void givenRunnableJar_whenExecuted_thenShouldRunSuccessfully() {
    Process process = null;
    try {
        String jarFile = new File(Objects.requireNonNull(getClass().getClassLoader()
          .getResource(RUNNABLE_JAR_PATH))
          .toURI()).getAbsolutePath();

        ProcessBuilder processBuilder = new ProcessBuilder("java", "-jar", jarFile);
        processBuilder.redirectErrorStream(true);

        process = processBuilder.start();
        try (InputStream inputStream = process.getInputStream()) {
            byte[] output = inputStream.readAllBytes();
            System.out.println("Output: " + new String(output));
        }

        int exitCode = process.waitFor();
        Assert.assertEquals("Process exited with an unexpected exit code", 0, exitCode);
    } catch (IOException | InterruptedException | URISyntaxException e) {
        Assert.fail("Test failed due to exception: " + e.getMessage());
    } finally {
        if (process != null) {
            process.destroy();
        }
    }
}

이 테스트는 실행 가능한 JAR가 성공적으로 실행되는지 확인합니다.

우리는 처음에 JAR 파일의 절대 경로를 제공하여 File 객체를 만들고 있습니다. getClass().getClassLoader().getResource(RUNNABLEJARPATH) 메서드는 리소스 URL을 가져오며, 이를 null이 아님을 확인하고 URI로 변환합니다.

그 다음, java -jar를 사용하여 명령을 설정하는데, 이는 실행 가능한 JAR를 실행하는 표준 방법입니다. 다음으로, 우리는 ProcessBuilder를 사용하여 JAR를 새로운 프로세스로 실행합니다.

실행이 시작되면, 입력 스트림에서 프로그램 출력 결과를 캡처하려고 시도합니다. 그리고 출력은 문자열로 변환되어 콘솔에 출력됩니다. 이는 java –jar 명령을 실행했을 때 볼 수 있는 것과 유사합니다.

그 후, process.waitFor()를 사용하여 프로세스가 완료될 때까지 기다립니다. 종료 코드가 0이면 실행이 성공적임을 나타냅니다. 종료 코드가 비-0 값이면, 실행 중 오류가 발생했음을 의미하며, 테스트가 실패합니다.

3. 실행 불가능한 JAR 파일 실행하기

실행 불가능한 JAR 파일은 매니페스트 파일에 Main-Class 속성이 없습니다. 우리는 main 메서드가 있는 클래스를 명시적으로 지정해야 합니다.

아래 코드는 프로그램적으로 실행 불가능한 JAR의 클래스 파일을 별도의 프로세스로 실행하고 출력 결과를 콘솔에서 확인하는 방법을 보여줍니다:

@Test
public void givenNonRunnableJar_whenExecutedWithMainClass_thenShouldRunSuccessfully() {
    Process process = null;
    try {
        String jarFile = new File(Objects.requireNonNull(getClass().getClassLoader()
          .getResource(NON_RUNNABLE_JAR_PATH))
          .toURI()).getAbsolutePath();

        String[] command = { "java", "-cp", jarFile, "com.company.HelloWorld", "arg1", "arg2" };
        ProcessBuilder processBuilder = new ProcessBuilder(command);
        processBuilder.redirectErrorStream(true);

        process = processBuilder.start();  // 프로세스 시작
        try (InputStream inputStream = process.getInputStream()) {
            byte[] output = inputStream.readAllBytes();
            System.out.println("Output: " + new String(output));
        }

        int exitCode = process.waitFor();
        Assert.assertEquals("Process exited with an unexpected exit code", 0, exitCode);
    } catch (IOException | InterruptedException | URISyntaxException e) {
        Assert.fail("Test failed due to exception: " + e.getMessage());
    } finally {
        if (process != null) {
            process.destroy();  // 모든 Java 버전에서 클린업 보장
        }
    }
}

위 테스트는 비실행 가능한 JAR에서 메인 클래스를 실행할 수 있는지 확인합니다.

처음에는 비실행 가능한 JAR 파일의 절대 경로를 제공하여 process.waitFor 객체를 생성합니다.

그 다음, 우리는 ProcessBuilder를 사용하여 실행 환경을 설정합니다. redirectErrorStream(true) 메서드는 오류 스트림을 표준 출력 스트림과 병합하여 모든 출력을 한 곳에서 캡처할 수 있게 합니다.

명령은 processBuilder.start()로 새로운 프로세스로 실행됩니다. 우리는 프로세스의 입력 스트림에서 프로그램의 출력을 캡처하고 이를 문자열로 변환하여 콘솔에 출력합니다. 출력은 우리가 수동으로 명령을 실행할 때 보는 출력과 유사합니다.

마지막으로, process.waitFor()를 사용하여 프로세스가 완료될 때까지 모니터링합니다.

종료 코드가 0이면 JAR가 성공적으로 실행된 것이고, 비-0 값이면 JAR 실행 중 오류가 발생한 것을 의미합니다.

4. 결론

이 기사에서는 Java 프로그램에서 JAR 파일 실행이 간단하다는 것을 살펴보았습니다. 실행 가능한 JAR를 실행하려면 클래스를 명시적으로 언급할 필요는 없지만, 비실행 가능한 JAR에서는 명시해야 합니다.

우리는 또한 ProcessBuilder 클래스를 사용하여 적절한 스트림 처리를 하고 JAR를 별도의 프로세스로 실행하는 방법을 보았습니다.

소스 코드 예제는 여기에서 찾을 수 있습니다.

원본 출처

You may also like...

답글 남기기

이메일 주소는 공개되지 않습니다. 필수 필드는 *로 표시됩니다