메모는나의성장

Java 9 Process API 개선

Spring

Java 9 Process API 개선

메모는나의열정 2021. 4. 1. 18:49
반응형

 

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 에서 찾을 수 있습니다 .

참고
  • https://docs.spring.io/spring-framework/docs/current/reference/html
  • https://www.baeldung.com/java-9-process-api
반응형