1. 소개
이 예제에서는 Process API 에 대해 자세히 살펴볼 것 입니다.
Process 를 사용 하여 쉘 명령을 실행하는 방법에 대해 더 자세히 알아 보려면 여기에서 이전 예제을 참조 할 수 있습니다 .
참조하는 프로세스는 실행중인 응용 프로그램입니다. 프로세스 클래스는, 출력을 추출하여 입력을 수행하는주기를 모니터링 종료 상태를 검사 포함 이러한 프로세스와 상호 작용하며 (사망)을 파괴하는 방법을 제공한다.
2. Java 프로그램 컴파일 및 실행을위한 프로세스 클래스 사용
Process API를 사용하여 다른 Java 프로그램을 컴파일하고 실행하는 예제를 살펴 보겠습니다 .
@Test
public void whenExecutedFromAnotherProgram_thenSourceProgramOutput3() throws IOException {
Process process = Runtime.getRuntime()
.exec("javac -cp src src\\main\\java\\com\\baeldung\\java9\\process\\OutputStreamExample.java");
process = Runtime.getRuntime()
.exec("java -cp src/main/java com.baeldung.java9.process.OutputStreamExample");
BufferedReader output = new BufferedReader(new InputStreamReader(process.getInputStream()));
int value = Integer.parseInt(output.readLine());
assertEquals(3, value);
}
따라서 기존 Java 코드 내에서 Java 코드를 실행하는 응용 프로그램은 사실상 제한이 없습니다.
3. 생성 프로세스
Java 응용 프로그램은 운영 체제 제한에 따라 컴퓨터 시스템 내에서 실행되는 모든 응용 프로그램을 호출 할 수 있습니다.
따라서 우리는 응용 프로그램을 실행할 수 있습니다. Process API를 활용하여 실행할 수있는 다양한 사용 사례를 살펴 보겠습니다.
ProcessBuilder를의 클래스는 우리가 우리의 응용 프로그램 내에서 하위 프로세스를 만들 수 있습니다.
Windows 기반 메모장 응용 프로그램을 여는 데모를 보겠습니다.
ProcessBuilder builder = new ProcessBuilder("notepad.exe");
Process process = builder.start();
4. 파기 절차
프로세스 는 또한 하위 프로세스 또는 프로세스를 파괴하는 방법을 제공합니다. 그러나 애플리케이션이 종료되는 방식은 플랫폼에 따라 다릅니다 .
가능한 다양한 사용 사례를 살펴 보겠습니다.
4.1. 참조로 프로세스 삭제
Windows OS를 사용 중이고 메모장 응용 프로그램을 생성하고 제거하려고한다고 가정 해 보겠습니다.
이전과 마찬가지로 ProcessBuilder 클래스와 start () 메서드 를 사용하여 메모장 응용 프로그램의 인스턴스를 만들 수 있습니다 .
그런 다음 Process 객체 에서 destroy () 메서드를 호출 할 수 있습니다 .
4.2. ID로 프로세스 삭제
또한 응용 프로그램에서 생성되지 않은 운영 체제 내에서 실행중인 프로세스를 종료 할 수도 있습니다.
이 작업을 수행하는 동안에는 운영 체제를 불안정하게 만들 수있는 중요한 프로세스가 무의식적으로 파괴 될 수 있으므로주의해야합니다 .
먼저 작업 관리자를 확인하여 현재 실행중인 프로세스의 프로세스 ID를 찾고 pid를 찾아야합니다.
예를 보겠습니다.
long pid = /* PID to kill */;
Optional<ProcessHandle> optionalProcessHandle = ProcessHandle.of(pid);
optionalProcessHandle.ifPresent(processHandle -> processHandle.destroy());
4.3. 강제로 프로세스 파괴
destroy () 메서드를 실행 하면 아티클의 앞부분에서 본 것처럼 하위 프로세스가 종료됩니다.
destroy () 가 작동하지 않는 경우 destroyForcibly () 옵션이 있습니다.
항상 destroy () 메소드 부터 시작해야합니다 . 그 후 isAlive () 를 실행하여 하위 프로세스에 대한 빠른 검사를 수행 할 수 있습니다 .
true를 반환하면 destroyForcibly () 실행합니다 .
ProcessBuilder builder = new ProcessBuilder("notepad.exe");
Process process = builder.start();
process.destroy();
if (process.isAlive()) {
process.destroyForcibly();
}
5. 프로세스 완료 대기
또한 두 개의 오버로드 된 메서드가 있으며이를 통해 프로세스 완료를 기다릴 수 있습니다.
5.1. 기다립니다()
이 메서드가 실행되면 하위 프로세스가 종료되지 않는 한 현재 실행 프로세스 스레드를 차단 대기 상태로 둡니다 .
예를 살펴 보겠습니다.
ProcessBuilder builder = new ProcessBuilder("notepad.exe");
Process process = builder.start();
assertThat(process.waitFor() >= 0);
위의 예에서 현재 스레드가 실행을 계속하려면 하위 프로세스 스레드가 끝날 때까지 기다릴 것입니다. 하위 프로세스가 종료되면 현재 스레드가 계속 실행됩니다.
5.2. waitfor (long timeOut, TimeUnit 시간)
이 메서드가 실행되면 하위 프로세스가 종료되거나 시간이 초과되지 않는 한 현재 실행 프로세스 스레드를 차단 대기 상태로 둡니다 .
예를 살펴 보겠습니다.
ProcessBuilder builder = new ProcessBuilder("notepad.exe");
Process process = builder.start();
assertFalse(process.waitFor(1, TimeUnit.SECONDS));
위의 예에서 현재 스레드가 실행을 계속하려면 하위 프로세스 스레드가 종료 될 때까지 또는 지정된 시간 간격이 경과 할 때까지 계속 대기합니다.
이 메서드가 실행되면 하위 프로세스가 종료 된 경우 부울 값 true를 반환하고 하위 프로세스가 종료되기 전에 대기 시간이 경과 한 경우 부울 값 false를 반환합니다.
6. exitValue ()
이 메서드가 실행되면 현재 스레드는 하위 프로세스가 종료되거나 파괴 될 때까지 기다리지 않지만 하위 프로세스가 종료되지 않은 경우 IllegalThreadStateException 을 throw합니다 .
다른 방법으로 하위 프로세스가 성공적으로 종료 된 경우 프로세스의 종료 값이 발생합니다 .
가능한 모든 양의 정수일 수 있습니다.
하위 프로세스가 성공적으로 종료되었을 때 exitValue () 메서드가 양의 정수를 반환 하는 예를 살펴 보겠습니다 .
@Test
public void
givenSubProcess_whenCurrentThreadWillNotWaitIndefinitelyforSubProcessToEnd_thenProcessExitValueReturnsGrt0()
throws IOException {
ProcessBuilder builder = new ProcessBuilder("notepad.exe");
Process process = builder.start();
assertThat(process.exitValue() >= 0);
}
7. isAlive ()
프로세스가 살아 있든 아니든 주관적인 업무 처리를 수행하고 싶을 때.
부울 값을 반환하는 프로세스가 살아 있는지 여부를 신속하게 확인할 수 있습니다.
간단한 예를 살펴 보겠습니다.
ProcessBuilder builder = new ProcessBuilder("notepad.exe");
Process process = builder.start();
Thread.sleep(10000);
process.destroy();
assertTrue(process.isAlive());
8. 프로세스 스트림 처리
기본적으로 생성 된 하위 프로세스에는 터미널이나 콘솔이 없습니다. 모든 표준 I / O (즉, stdin, stdout, stderr) 작업은 상위 프로세스로 전송됩니다. 따라서 부모 프로세스는 이러한 스트림을 사용하여 하위 프로세스에 입력을 공급하고 출력을 가져올 수 있습니다.
결과적으로 이것은 우리에게 하위 프로세스의 입력 / 출력을 제어 할 수있는 엄청난 유연성을 제공합니다.
8.1. getErrorStream ()
흥미롭게도 하위 프로세스에서 발생한 오류를 가져 와서 비즈니스 처리를 수행 할 수 있습니다.
그런 다음 요구 사항에 따라 특정 비즈니스 처리 검사를 실행할 수 있습니다.
예를 보겠습니다.
@Test
public void givenSubProcess_whenEncounterError_thenErrorStreamNotNull() throws IOException {
Process process = Runtime.getRuntime().exec(
"javac -cp src src\\main\\java\\com\\baeldung\\java9\\process\\ProcessCompilationError.java");
BufferedReader error = new BufferedReader(new InputStreamReader(process.getErrorStream()));
String errorString = error.readLine();
assertNotNull(errorString);
}
8.2. getInputStream ()
또한 하위 프로세스에서 생성 된 출력을 가져와 상위 프로세스 내에서 소비하여 프로세스간에 정보를 공유 할 수 있습니다.
@Test
public void givenSourceProgram_whenReadingInputStream_thenFirstLineEquals3() throws IOException {
Process process = Runtime.getRuntime().exec(
"javac -cp src src\\main\\java\\com\\baeldung\\java9\\process\\OutputStreamExample.java");
process = Runtime.getRuntime()
.exec("java -cp src/main/java com.baeldung.java9.process.OutputStreamExample");
BufferedReader output = new BufferedReader(new InputStreamReader(process.getInputStream()));
int value = Integer.parseInt(output.readLine());
assertEquals(3, value);
}
8.3. ge tOutputStream ()
상위 프로세스에서 하위 프로세스로 입력을 보낼 수 있습니다.
Writer w = new OutputStreamWriter(process.getOutputStream(), "UTF-8");
w.write("send to child\n");
8.4. 프로세스 스트림 필터링
선택적 실행 프로세스와 상호 작용하는 것은 완벽하게 유효한 사용 사례입니다.
Process 는 특정 술어에 따라 실행중인 프로세스를 선택적으로 필터링하는 기능을 제공합니다.
그 후에 우리는이 선택적 프로세스 세트에서 비즈니스 운영을 수행 할 수 있습니다.
@Test
public void givenRunningProcesses_whenFilterOnProcessIdRange_thenGetSelectedProcessPid() {
assertThat(((int) ProcessHandle.allProcesses()
.filter(ph -> (ph.pid() > 10000 && ph.pid() < 50000))
.count()) > 0);
}
9. 결론
프로세스 는 운영 체제 수준의 상호 작용을위한 강력한 클래스입니다. 터미널 명령을 트리거하고 응용 프로그램을 시작, 모니터링 및 종료합니다.
- https://docs.spring.io/spring-framework/docs/current/reference/html
- https://www.baeldung.com/java-process-api
'Java' 카테고리의 다른 글
Spring MultipartFile을 파일로 변환 (0) | 2021.03.28 |
---|---|
Spring @PathVariable 어노테이션 (0) | 2021.03.28 |
Spring REST API의 바이너리 데이터 형식 (0) | 2021.03.28 |
Spring Boot에서 Keycloak 사용에 대한 빠른 사용방법(예제) (0) | 2021.03.28 |
Spring Boot에서 프로필에 대한 Security 비활성화 (0) | 2021.03.27 |