Java : ProcessHandle (外部プロセス) - API使用例
ProcessHandle (Java SE 19 & JDK 19) の使用例まとめです。
だいたいのメソッドを網羅済みです。
API仕様のおともにどうぞ。
概要
ProcessHandle インタフェースは、外部プロセスの制御に使います。
プロセスの情報を取得したり、プロセスを強制終了させたりすることができます。
似たクラスに Process クラスがあります。
Process クラスは、ProcessBuilder で起動したプロセスです。
自分で起動したプロセスのため、標準出力や標準入力の制御もできます。
ProcessHandle は ProcessBuilder で起動していないプロセスの制御もできます。
代わりに、標準出力や標準入力の制御はできません。
public class Main {
public static void main(String[] args) {
final var handle = ProcessHandle.current();
final var pid = handle.pid();
System.out.println("pid = " + pid);
final var info = handle.info();
System.out.println("user = " + info.user());
System.out.println("total cpu time = " + info.totalCpuDuration());
}
}
// 結果
// ↓
//> java Main
//pid = 11908
//user = Optional[MY-PC\xxxx]
//total cpu time = Optional[PT0.125S]
メソッド
static Stream<ProcessHandle> allProcesses ()
final var stream = ProcessHandle.allProcesses();
stream.forEach(handle -> {
handle.info().command().ifPresent(command -> {
System.out.println("command : " + command);
});
});
// 結果
// ↓
//command : C:\Windows\System32\sihost.exe
//command : C:\Windows\System32\svchost.exe
//command : C:\Windows\System32\taskhostw.exe
//...
//command : C:\Windows\System32\notepad.exe
//command : C:\Windows\System32\mspaint.exe
//...
Stream<ProcessHandle> children ()
public class ChildA {
public static void main(String[] args) throws InterruptedException {
TimeUnit.SECONDS.sleep(2);
}
}
public class ChildB {
public static void main(String[] args) throws InterruptedException {
TimeUnit.SECONDS.sleep(2);
}
}
public class Main {
public static void main(String[] args) throws IOException, InterruptedException {
System.out.println("main : start");
final var processA = new ProcessBuilder("java", "ChildA").inheritIO().start();
System.out.println(" child A pid = " + processA.pid());
final var processB = new ProcessBuilder("java", "ChildB").inheritIO().start();
System.out.println(" child B pid = " + processB.pid());
TimeUnit.SECONDS.sleep(1);
System.out.println("-- children --");
final var stream = ProcessHandle.current().children();
stream.forEach(handle -> System.out.println("pid : " + handle.pid()));
System.out.println("--------------");
processA.waitFor();
processB.waitFor();
System.out.println("main : end");
}
}
// 結果
// ↓
//> java Main
//main : start
// child A pid = 4784
// child B pid = 10488
//-- children --
//pid : 4784
//pid : 10488
//--------------
//main : end
int compareTo (ProcessHandle other)
public class Child {
public static void main(String[] args) throws InterruptedException {
TimeUnit.SECONDS.sleep(2);
}
}
public class Main {
public static void main(String[] args) throws IOException, InterruptedException {
final var process = new ProcessBuilder("java", "Child").start();
final var current = ProcessHandle.current();
System.out.println("current : pid = " + current.pid());
final var child = process.toHandle();
System.out.println("child : pid = " + child.pid());
System.out.println("compare to 1 : " + current.compareTo(child));
System.out.println("compare to 2 : " + child.compareTo(current));
System.out.println("compare to 3 : " + current.compareTo(current));
process.waitFor();
}
}
// 結果
// ↓
//> java Main
//current : pid = 14972
//child : pid = 7272
//compare to 1 : 1
//compare to 2 : -1
//compare to 3 : 0
static ProcessHandle current ()
public class Child {
public static void main(String[] args) {
System.out.println("child : start");
final var current = ProcessHandle.current();
System.out.println(" child current pid = " + current.pid());
current.parent().ifPresent(parent -> {
System.out.println(" child parent pid = " + parent.pid());
});
System.out.println("child : end");
}
}
public class Main {
public static void main(String[] args) throws IOException, InterruptedException {
System.out.println("main : start");
final var process = new ProcessBuilder("java", "Child").inheritIO().start();
System.out.println("main : child pid = " + process.pid());
final var current = ProcessHandle.current();
System.out.println("main : current pid = " + current.pid());
process.waitFor();
System.out.println("main : end");
}
}
// 結果
// ↓
//> java Main
//main : start
//main : child pid = 16612
//main : current pid = 3476
//child : start
// child current pid = 16612
// child parent pid = 3476
//child : end
//main : end
Stream<ProcessHandle> descendants ()
public class DescendantA {
public static void main(String[] args) throws InterruptedException {
TimeUnit.SECONDS.sleep(2);
}
}
public class DescendantB {
public static void main(String[] args) throws InterruptedException {
TimeUnit.SECONDS.sleep(2);
}
}
public class Child {
public static void main(String[] args) throws IOException, InterruptedException {
System.out.println("child : start");
final var processA = new ProcessBuilder("java", "DescendantA").inheritIO().start();
System.out.println(" descendant A pid = " + processA.pid());
final var processB = new ProcessBuilder("java", "DescendantB").inheritIO().start();
System.out.println(" descendant B pid = " + processB.pid());
processA.waitFor();
processB.waitFor();
System.out.println("child : end");
}
}
public class Main {
public static void main(String[] args) throws IOException, InterruptedException {
System.out.println("main : start");
final var process = new ProcessBuilder("java", "Child").inheritIO().start();
System.out.println(" child pid = " + process.pid());
TimeUnit.SECONDS.sleep(1);
System.out.println("-- descendants --");
final var stream = ProcessHandle.current().descendants();
stream.forEach(handle -> {
System.out.println("pid : " + handle.pid());
});
System.out.println("--------------");
process.waitFor();
System.out.println("main : end");
}
}
// 結果
// ↓
//> java Main
//main : start
// child pid = 21016
//child : start
// descendant A pid = 15960
// descendant B pid = 17192
//-- descendants --
//pid : 21016
//pid : 15960
//pid : 17192
//--------------
//child : end
//main : end
boolean destroy ()
public class Child {
public static void main(String[] args) throws InterruptedException {
System.out.println("child : start");
TimeUnit.SECONDS.sleep(5);
System.out.println("child : end");
}
}
public class Main {
public static void main(String[] args) throws IOException, InterruptedException {
System.out.println("main : start");
final var process = new ProcessBuilder("java", "Child").inheritIO().start();
TimeUnit.SECONDS.sleep(1);
if (args.length == 1 && "destroy".equals(args[0])) {
final var handle = process.toHandle();
System.out.println("destroy : " + handle.destroy());
}
System.out.println("waitFor : " + process.waitFor());
System.out.println("main : end");
}
}
// 結果
// ↓
//> java Main
//main : start
//child : start
//child : end
//waitFor : 0
//main : end
//
//> java Main destroy
//main : start
//child : start
//destroy : true
//waitFor : 1
//main : end
boolean destroyForcibly ()
public class Child {
public static void main(String[] args) throws InterruptedException {
System.out.println("child : start");
TimeUnit.SECONDS.sleep(5);
System.out.println("child : end");
}
}
public class Main {
public static void main(String[] args) throws IOException, InterruptedException {
System.out.println("main : start");
final var process = new ProcessBuilder("java", "Child").inheritIO().start();
TimeUnit.SECONDS.sleep(1);
if (args.length == 1 && "destroy".equals(args[0])) {
final var handle = process.toHandle();
System.out.println("destroy : " + handle.destroyForcibly());
}
System.out.println("waitFor : " + process.waitFor());
System.out.println("main : end");
}
}
// 結果
// ↓
//> java Main
//main : start
//child : start
//child : end
//waitFor : 0
//main : end
//
//> java Main destroy
//main : start
//child : start
//destroy : true
//waitFor : 1
//main : end
boolean equals (Object other)
public class Child {
public static void main(String[] args) throws InterruptedException {
TimeUnit.SECONDS.sleep(2);
}
}
public class Main {
public static void main(String[] args) throws IOException, InterruptedException {
final var process = new ProcessBuilder("java", "Child").start();
final var current = ProcessHandle.current();
System.out.println("current : pid = " + current.pid());
final var child = process.toHandle();
System.out.println("child : pid = " + child.pid());
System.out.println("equals 1 : " + current.equals(child));
System.out.println("equals 2 : " + child.equals(current));
System.out.println("equals 3 : " + current.equals(current));
process.waitFor();
}
}
// 結果
// ↓
//> java Main
//current : pid = 19488
//child : pid = 5440
//equals 1 : false
//equals 2 : false
//equals 3 : true
int hashCode ()
public class Child {
public static void main(String[] args) throws InterruptedException {
TimeUnit.SECONDS.sleep(2);
}
}
public class Main {
public static void main(String[] args) throws IOException, InterruptedException {
final var process = new ProcessBuilder("java", "Child").start();
final var current = ProcessHandle.current();
System.out.println("current : pid = " + current.pid());
System.out.println("current : hashCode = " + current.hashCode());
final var child = process.toHandle();
System.out.println("child : pid = " + child.pid());
System.out.println("child : hashCode = " + child.hashCode());
process.waitFor();
}
}
// 結果
// ↓
//> java Main
//current : pid = 7260
//current : hashCode = 7260
//child : pid = 16924
//child : hashCode = 16924
ProcessHandle.Info info ()
public class Main {
public static void main(String[] args) throws IOException, InterruptedException {
final var current = ProcessHandle.current();
System.out.println("pid : " + current.pid());
final var info = current.info();
System.out.println("user : " + info.user());
System.out.println("total cpu time : " + info.totalCpuDuration());
}
}
// 結果
// ↓
//> java Main
//pid : 12276
//user : Optional[MY-PC\xxxx]
//total cpu time : Optional[PT0.125S]
boolean isAlive ()
public class Child {
public static void main(String[] args) throws InterruptedException {
TimeUnit.SECONDS.sleep(5);
}
}
public class Main {
public static void main(String[] args) throws IOException, InterruptedException, ExecutionException {
System.out.println("main : start");
final var process = new ProcessBuilder("java", "Child").start();
TimeUnit.SECONDS.sleep(1);
final var child = process.toHandle();
System.out.println("child : pid = " + child.pid());
System.out.println("child : isAlive = " + child.isAlive());
final var ret = child.onExit().thenApply(handle -> {
System.out.println("apply : pid = " + handle.pid());
System.out.println("apply : isAlive = " + handle.isAlive());
return handle;
}).get();
System.out.println("ret = " + ret.pid());
System.out.println("main : end");
}
}
// 結果
// ↓
//> java Main
//main : start
//child : pid = 1572
//child : isAlive = true
//apply : pid = 1572
//apply : isAlive = false
//ret = 1572
//main : end
static Optional<ProcessHandle> of (long pid)
public class Child {
public static void main(String[] args) throws InterruptedException {
TimeUnit.SECONDS.sleep(2);
}
}
public class Main {
public static void main(String[] args) throws IOException, InterruptedException {
final var process = new ProcessBuilder("java", "Child").start();
final var pid = process.pid();
System.out.println("pid = " + pid);
ProcessHandle.of(pid).ifPresent(handle -> {
System.out.println("handle : pid = " + handle.pid());
});
process.waitFor();
}
}
// 結果
// ↓
//> java Main
//pid = 22196
//handle : pid = 22196
CompletableFuture<ProcessHandle> onExit ()
このメソッドの使用例は、isAlive() にまとめて記載しました。
そちらのAPI使用例をご参照ください。
Optional<ProcessHandle> parent ()
このメソッドの使用例は、current() にまとめて記載しました。
そちらのAPI使用例をご参照ください。
long pid ()
このメソッドの使用例は、current() にまとめて記載しました。
そちらのAPI使用例をご参照ください。
boolean supportsNormalTermination ()
final var current = ProcessHandle.current();
System.out.println(current.supportsNormalTermination()); // false