1. 개요
Java의 프로세스 API는 Java 5 이전에 매우 원시적 이었지만 새 프로세스를 생성하는 유일한 방법은 Runtime.getRuntime (). exec () API를 사용하는 것입니다. 그런 다음 Java 5에서 새 프로세스를 생성하는 더 깨끗한 방법을 지원하는 ProcessBuilder API가 도입되었습니다.
Java 9는 현재 및 생성 된 프로세스에 대한 정보를 얻는 새로운 방법을 추가합니다.
이 기사에서는 이러한 향상된 기능을 모두 살펴볼 것입니다.
2. 현재 Java 프로세스 정보
이제 API java.lang.ProcessHandle.Info API 를 통해 프로세스에 대한 많은 정보를 얻을 수 있습니다 .
- 프로세스를 시작하는 데 사용되는 명령
- 명령의 인수
- 프로세스가 시작된 순간
- 그것과 그것을 만든 사용자가 보낸 총 시간
이를 수행하는 방법은 다음과 같습니다.
@Test
public void givenCurrentProcess_whenInvokeGetInfo_thenSuccess()
throws IOException {
ProcessHandle processHandle = ProcessHandle.current();
ProcessHandle.Info processInfo = processHandle.info();
assertNotNull(processHandle.getPid());
assertEquals(true, processInfo.arguments().isPresent());
assertEquals(true, processInfo.command().isPresent());
assertTrue(processInfo.command().get().contains("java"));
assertEquals(true, processInfo.startInstant().isPresent());
assertEquals(false,
processInfo.totalCpuDuration().isPresent());
assertEquals(true, processInfo.user().isPresent());
}
java.lang.ProcessHandle.Info 는 다른 인터페이스 java.lang.ProcessHandle 내에 정의 된 공용 인터페이스라는 점에 유의해야합니다 . JDK 공급자 (Oracle JDK, Open JDK, Zulu 또는 기타)는 이러한 구현이 프로세스에 대한 관련 정보를 반환하는 방식으로 이러한 인터페이스에 구현을 제공해야합니다.
3. 생성 된 프로세스 정보
새로 생성 된 프로세스의 프로세스 정보를 얻을 수도 있습니다. 이 경우 프로세스를 생성하고 java.lang.Process 의 인스턴스를 얻은 후에는 toHandle () 메서드를 호출하여 java.lang.ProcessHandle 의 인스턴스를 얻습니다 .
나머지 세부 사항은 위 섹션에서와 동일하게 유지됩니다.
String javaCmd = ProcessUtils.getJavaCmd().getAbsolutePath();
ProcessBuilder processBuilder = new ProcessBuilder(javaCmd, "-version");
Process process = processBuilder.inheritIO().start();
ProcessHandle processHandle = process.toHandle();
4. 시스템의 라이브 프로세스 열거
현재 프로세스에서 볼 수있는 현재 시스템에있는 모든 프로세스를 나열 할 수 있습니다. 반환 된 List은 API가 호출 된 시점의 스냅 샷이므로 스냅 샷을 찍은 후 일부 프로세스가 종료되거나 일부 새 프로세스가 추가되었을 수 있습니다.
그렇게하기 위해, 우리는 정적 메소드 사용할 수 있습니다 allProcesses () 에서 사용할 수 java.lang.ProcessHandle의 우리에게 반환 인터페이스 스트림 의 ProcessHandle를 :
@Test
public void givenLiveProcesses_whenInvokeGetInfo_thenSuccess() {
Stream<ProcessHandle> liveProcesses = ProcessHandle.allProcesses();
liveProcesses.filter(ProcessHandle::isAlive)
.forEach(ph -> {
assertNotNull(ph.getPid());
}
5. 자식 프로세스 열거
이를 수행하는 두 가지 변형이 있습니다.
- 현재 프로세스의 직계 자식 확보
- 현재 프로세스의 모든 자손 가져 오기
전자는 children () 메서드를 사용하여 달성되고 후자는 자손 () 메서드를 사용하여 달성됩니다 .
@Test
public void givenProcess_whenGetChildProcess_thenSuccess()
throws IOException{
int childProcessCount = 5;
for (int i = 0; i < childProcessCount; i++){
String javaCmd = ProcessUtils.getJavaCmd()
.getAbsolutePath();
ProcessBuilder processBuilder
= new ProcessBuilder(javaCmd, "-version");
processBuilder.inheritIO().start();
}
Stream<ProcessHandle> children
= ProcessHandle.current().children();
children.filter(ProcessHandle::isAlive)
.forEach(ph -> log.info("PID: {}, Cmd: {}",
ph.getPid(), ph.info().command()));
// and for descendants
Stream<ProcessHandle> descendants
= ProcessHandle.current().descendants();
descendants.filter(ProcessHandle::isAlive)
.forEach(ph -> log.info("PID: {}, Cmd: {}",
ph.getPid(), ph.info().command()));
}
6. 프로세스 종료시 종속 작업 트리거
프로세스가 종료되면 무언가를 실행하고 싶을 수 있습니다. 이는 java.lang.ProcessHandle 인터페이스 의 onExit () 메소드를 사용하여 수행 할 수 있습니다 . 이 메서드는 CompletableFuture 가 완료 될 때 종속 작업을 트리거하는 기능을 제공 하는 CompletableFuture 를 반환합니다 .
여기서 CompletableFuture 는 프로세스가 완료되었음을 나타내지 만 프로세스가 성공적으로 완료되었는지 여부는 중요하지 않습니다. CompletableFuture 에서 get () 메서드를 호출하여 완료를 기다립니다.
@Test
public void givenProcess_whenAddExitCallback_thenSuccess()
throws Exception {
String javaCmd = ProcessUtils.getJavaCmd()
.getAbsolutePath();
ProcessBuilder processBuilder
= new ProcessBuilder(javaCmd, "-version");
Process process = processBuilder.inheritIO()
.start();
ProcessHandle processHandle = process.toHandle();
log.info("PID: {} has started", processHandle.getPid());
CompletableFuture<ProcessHandle> onProcessExit
= processHandle.onExit();
onProcessExit.get();
assertEquals(false, processHandle.isAlive());
onProcessExit.thenAccept(ph -> {
log.info("PID: {} has stopped", ph.getPid());
});
}
의 OnExit () 메소드는 가능하다 java.lang.Process의 용 뿐만 아니라 인터페이스.
7. 결론
이 예제에서는 실행 및 생성 된 프로세스를 훨씬 더 많이 제어 할 수있는 Java 9 의 Process API에 대한 흥미로운 추가 사항에 대해 설명했습니다 .
이 기사에서 사용 된 코드 는 GitHub 에서 찾을 수 있습니다 .