Java : ProcessHandle with Examples

ProcessHandle (Java SE 19 & JDK 19) API Examples.
You will find code examples on most ProcessHandle methods.


Summary

ProcessHandle identifies and provides control of native processes. Each individual process can be monitored for liveness, list its children, get information about the process or destroy it.

Class diagram

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());
    }
}

// Result
// ↓
//> java Main
//pid = 11908
//user = Optional[MY-PC\xxxx]
//total cpu time = Optional[PT0.125S]

Methods

static Stream<ProcessHandle> allProcesses ()

Returns a snapshot of all processes visible to the current process.

final var stream = ProcessHandle.allProcesses();
stream.forEach(handle -> {
    handle.info().command().ifPresent(command -> {
        System.out.println("command : " + command);
    });
});

// Result
// ↓
//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 ()

Returns a snapshot of the current direct children of the process.

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");
    }
}

// Result
// ↓
//> java Main
//main : start
//  child A pid = 4784
//  child B pid = 10488
//-- children --
//pid : 4784
//pid : 10488
//--------------
//main : end

int compareTo (ProcessHandle other)

Compares this ProcessHandle with the specified ProcessHandle for order.

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();
    }
}

// Result
// ↓
//> java Main
//current : pid = 14972
//child : pid = 7272
//compare to 1 : 1
//compare to 2 : -1
//compare to 3 : 0

static ProcessHandle current ()

Returns a ProcessHandle for the current process.

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");
    }
}

// Result
// ↓
//> 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 ()

Returns a snapshot of the descendants of the process.

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");
    }
}

// Result
// ↓
//> 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 ()

Requests the process to be killed.

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");
    }
}

// Result
// ↓
//> 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 ()

Requests the process to be killed forcibly.

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");
    }
}

// Result
// ↓
//> 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)

Returns true if other object is non-null, is of the same implementation, and represents the same system process; otherwise it returns false.

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();
    }
}

// Result
// ↓
//> java Main
//current : pid = 19488
//child : pid = 5440
//equals 1 : false
//equals 2 : false
//equals 3 : true

int hashCode ()

Returns a hash code value for this ProcessHandle.

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();
    }
}

// Result
// ↓
//> java Main
//current : pid = 7260
//current : hashCode = 7260
//child : pid = 16924
//child : hashCode = 16924

ProcessHandle.Info info ()

Returns a snapshot of information about the process.

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());
    }
}

// Result
// ↓
//> java Main
//pid : 12276
//user : Optional[MY-PC\xxxx]
//total cpu time : Optional[PT0.125S]

boolean isAlive ()

Tests whether the process represented by this ProcessHandle is alive.

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");
    }
}

// Result
// ↓
//> 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)

Returns an Optional<ProcessHandle> for an existing native process.

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();
    }
}

// Result
// ↓
//> java Main
//pid = 22196
//handle : pid = 22196

CompletableFuture<ProcessHandle> onExit ()

Returns a CompletableFuture<ProcessHandle> for the termination of the process.

Please see isAlive().

Optional<ProcessHandle> parent ()

Returns an Optional<ProcessHandle> for the parent process.

Please see current().

long pid ()

Returns the native process ID of the process.

Please see current().

boolean supportsNormalTermination ()

Returns true if the implementation of destroy() normally terminates the process.

final var current = ProcessHandle.current();
System.out.println(current.supportsNormalTermination()); // false

Related posts

To top of page