Computer >> 컴퓨터 >  >> 프로그래밍 >> Java

Java 9 JShell로 프로세스 PID·정보·자식 프로세스 확인 및 종료하는 방법

JShell은 클래스, 메서드, 인터페이스, 열거형(enum) 등 간단한 Java 구문을 입력하면 즉시 평가하고 그 결과를 명령줄(command-line) 프롬프트에 출력해 주는 Java Shell 도구입니다.

Java 9에서는 운영체제 프로세스를 보다 효과적으로 관리하고 제어할 수 있도록 Process API가 대폭 개선되었습니다. 새롭게 추가된 ProcessHandle 인터페이스는 네이티브 프로세스를 식별하고 제어하는 기능을 제공하며, 프로세스의 생존 여부(liveness)를 확인하거나 프로세스를 종료(destroy)하는 메서드도 포함하고 있습니다. 또한 ProcessHandle.Info 인터페이스는 특정 프로세스에 대한 정보 스냅샷(snapshot)을 제공합니다.

아래 코드 예제에서는 JShell 도구를 활용하여 Process API의 pid(프로세스 ID), info(프로세스 정보), children(자식 프로세스), destroy(프로세스 종료) 기능을 단계별로 확인하는 방법을 살펴봅니다.

코드 예제

jshell> ProcessHandle currentProcess = ProcessHandle.current();
currentProcess ==> 3960

jshell> System.out.println("Current Process Id: = " + currentProcess.pid());
Current Process Id: = 3960

jshell> currentProcess.info();
$3 ==> [user: Optional[Tutorialspoint\User], cmd: C:\Program Files\Java\jdk-9.0.4\bin\java.exe, startTime: Optional[2020-05-03T06:43:37.510Z], totalTime: Optional[PT1.265625S]]

jshell> currentProcess.pid();
$4 ==> 3960

jshell> ProcessHandle.of(3960)
$5 ==> Optional[3960]

jshell> $5.get()
$6 ==> 3960

jshell> $6.info()
$7 ==> [user: Optional[Tutorialspoint\User], cmd: C:\Program Files\Java\jdk-9.0.4\bin\java.exe, startTime: Optional[2020-05-03T06:43:37.510Z], totalTime: Optional[PT1.390625S]]

jshell> Stream<ProcessHandle> childProc = ProcessHandle.current().children();
childProc ==> java.util.stream.ReferencePipeline$2@6895a785

jshell> childProc.count()
$10 ==> 1

jshell> childProc.forEach(procHandle -> { System.out.println(procHandle.destroy() ? "Could not kill process " + procHandle.pid() : "Terminated " + procHandle.pid()); });

| java.lang.IllegalStateException thrown: stream has already been operated upon or closed
| at AbstractPipeline.evaluate (AbstractPipeline.java:229)
| at ReferencePipeline.forEach (ReferencePipeline.java:430)
| at (#11:1)

단계별 설명

1. 현재 프로세스 핸들 가져오기

ProcessHandle.current() 메서드를 호출하면 현재 실행 중인 프로세스의 핸들을 얻을 수 있습니다. 위 예제에서는 PID가 3960인 프로세스가 반환되었습니다.

2. 프로세스 ID(PID) 확인

currentProcess.pid() 메서드는 해당 프로세스의 고유 식별자인 PID를 long 타입으로 반환합니다.

3. 프로세스 정보 스냅샷 조회

info() 메서드는 프로세스를 실행한 사용자(user), 실행 명령(cmd), 시작 시간(startTime), 누적 CPU 사용 시간(totalTime) 등의 정보를 담은 스냅샷을 반환합니다.

4. 특정 PID로 프로세스 조회

ProcessHandle.of(pid) 메서드는 지정된 PID에 해당하는 프로세스 핸들을 Optional<ProcessHandle> 형태로 반환합니다. 해당 PID의 프로세스가 존재하지 않으면 빈 Optional이 반환됩니다.

5. 자식 프로세스 탐색

children() 메서드는 현재 프로세스의 직계 자식 프로세스들을 Stream<ProcessHandle> 형태로 반환합니다. 위 예제에서는 자식 프로세스가 1개 존재하는 것으로 확인됩니다.

6. 프로세스 종료 시 주의사항

마지막 예제에서 IllegalStateException: stream has already been operated upon or closed 오류가 발생했습니다. Java의 스트림(Stream)은 일회성(one-time use) 객체이기 때문입니다. 앞서 count() 최종 연산을 호출하는 순간 해당 스트림은 소비된 상태가 되므로, 동일한 스트림 객체로 forEach()를 다시 호출하면 예외가 발생합니다. 이를 해결하려면 ProcessHandle.current().children()을 다시 호출하여 새로운 스트림을 생성한 뒤 destroy()와 함께 사용해야 합니다.