広告

Java : Process (外部プロセス) - API使用例

Process (Java SE 19 & JDK 19) の使用例まとめです。
だいたいのメソッドを網羅済みです。
API仕様のおともにどうぞ。


概要

Processは、ProcessBuilder.startおよびRuntime.execによって開始されたネイティブ・プロセスの制御を提供します。 このクラスは、プロセスからの入力の実行、プロセスへの出力の実行、プロセスの完了を待つプロセスの終了ステータスのチェック、プロセスの破棄(kill)を行うメソッドを提供します。

クラス構成

Processクラスは、ProcessBuilder で起動された外部プロセスを表します。
外部プロセスの標準出力や標準エラーを受け取ることもできます。

public class Child {
    public static void main(String[] args) {
        System.out.println("  TEST 1");
        System.out.println("  TEST 2");
        System.out.println("  TEST 3");
    }
}
public class Main {
    public static void main(String[] args) throws IOException, InterruptedException {
        System.out.println("main : start");

        final var process = new ProcessBuilder("java", "Child").start();
        try (final var reader = process.inputReader()) {
            reader.lines().forEach(System.out::println);
        }

        System.out.println("waitFor : " + process.waitFor());

        System.out.println("main : end");
    }
}

// 結果
// ↓
//> java Main
//main : start
//  TEST 1
//  TEST 2
//  TEST 3
//waitFor : 0
//main : end

コンストラクタ

Process ()

Processのデフォルトのコンストラクタです。

抽象クラスの Process を直接作成することは少ないと思うので、コード例は割愛します。

メソッド

Stream<ProcessHandle> children ()

プロセスの直接の子のスナップショットを返します。

public class Parent {
    public static void main(String[] args) throws IOException, InterruptedException {
        System.out.println("parent : 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());

        processA.waitFor();
        processB.waitFor();

        System.out.println("parent : end");
    }
}
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 process = new ProcessBuilder("java", "Parent").inheritIO().start();
        TimeUnit.SECONDS.sleep(1);

        System.out.println("-- children --");
        final var stream = process.children();
        stream.forEach(processHandle -> {
            System.out.println("process handle : " + processHandle);
        });
        System.out.println("--------------");

        System.out.println("waitFor : " + process.waitFor());

        System.out.println("main : end");
    }
}

// 結果
// ↓
//> java Main
//main : start
//parent : start
//  child A pid = 7936
//  child B pid = 22724
//-- children --
//process handle : 7936
//process handle : 22724
//--------------
//parent : end
//waitFor : 0
//main : end

Stream<ProcessHandle> descendants ()

プロセスの子孫のスナップショットを返します。

public class Parent {
    public static void main(String[] args) throws IOException, InterruptedException {
        System.out.println("parent : start");

        final var process = new ProcessBuilder("java", "Child").inheritIO().start();
        System.out.println("  child pid = " + process.pid());

        process.waitFor();

        System.out.println("parent : end");
    }
}
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 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 Main {
    public static void main(String[] args) throws IOException, InterruptedException {
        System.out.println("main : start");

        final var process = new ProcessBuilder("java", "Parent").inheritIO().start();
        TimeUnit.SECONDS.sleep(1);

        System.out.println("-- descendants --");
        final var stream = process.descendants();
        stream.forEach(processHandle -> {
            System.out.println("process handle : " + processHandle);
        });
        System.out.println("--------------");

        System.out.println("waitFor : " + process.waitFor());

        System.out.println("main : end");
    }
}

// 結果
// ↓
//> java Main
//main : start
//parent : start
//  child pid = 21596
//child : start
//  descendant A pid = 3456
//  descendant B pid = 21224
//-- descendants --
//process handle : 21596
//process handle : 3456
//process handle : 21224
//--------------
//child : end
//parent : end
//waitFor : 0
//main : end

abstract void 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])) {
            System.out.println("Destroy!");
            process.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!
//waitFor : 1
//main : end

Process 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();
        System.out.println("process : " + process);

        TimeUnit.SECONDS.sleep(1);

        if (args.length == 1 && "destroy".equals(args[0])) {
            System.out.println("destroy : " + process.destroyForcibly());
        }
        System.out.println("waitFor : " + process.waitFor());

        System.out.println("main : end");
    }
}

// 結果
// ↓
//> java Main
//main : start
//process : Process[pid=23168, exitValue="not exited"]
//child : start
//child : end
//waitFor : 0
//main : end
//
//> java Main destroy
//main : start
//process : Process[pid=17924, exitValue="not exited"]
//child : start
//destroy : Process[pid=17924, exitValue=1]
//waitFor : 1
//main : end

final BufferedReader errorReader ()

プロセスの標準エラーに接続されたBufferedReaderを返します。

public class Child {
    public static void main(String[] args) {
        System.out.println("  OUT 1");
        System.err.println("  ERR 1");
        System.out.println("  OUT 2");
        System.err.println("  ERR 2");
    }
}
public class Main {
    public static void main(String[] args) throws IOException, InterruptedException {
        System.out.println("main : start");

        final var process = new ProcessBuilder("java", "Child").start();
        try (final var reader = process.errorReader()) {
            reader.lines().forEach(System.out::println);
        }

        System.out.println("waitFor : " + process.waitFor());

        System.out.println("main : end");
    }
}

// 結果
// ↓
//> java Main
//main : start
//  ERR 1
//  ERR 2
//waitFor : 0
//main : end

final BufferedReader errorReader (Charset charset)

Charsetを使用してこのプロセスの標準エラーに接続されたBufferedReaderを返します。

public class Child {
    public static void main(String[] args) {
        System.err.println("stderr.encoding = " + System.getProperty("stderr.encoding"));
        System.err.println("ERR : ○△×");
    }
}
public class Main {
    public static void main(String[] args) throws IOException, InterruptedException {
        System.out.println("main : start");

        final var charset = Charset.forName("UTF-32");

        final var process = new ProcessBuilder("java", "-Dstderr.encoding=UTF-32", "Child").start();
        try (final var reader = process.errorReader(charset)) {
            reader.lines().forEach(System.out::println);
        }

        System.out.println("waitFor : " + process.waitFor());

        System.out.println("main : end");
    }
}

// 結果
// ↓
//> java Main
//main : start
//stderr.encoding = UTF-32
//ERR : ○△×
//waitFor : 0
//main : end

abstract int exitValue ()

プロセスの終了値を返します。

public class ChildA {
    public static void main(String[] args) throws InterruptedException {
        System.out.println("child A : start");

        TimeUnit.SECONDS.sleep(5);

        System.out.println("child A : end");
    }
}
public class ChildB {
    public static void main(String[] args) throws InterruptedException {
        System.out.println("child B : start");

        TimeUnit.SECONDS.sleep(5);

        System.out.println("child B : end");
        System.exit(-100);
    }
}
public class Main {
    public static void main(String[] args) throws IOException, InterruptedException {
        System.out.println("main : start");

        System.out.println("-- process A --");
        final var processA = new ProcessBuilder("java", "ChildA").inheritIO().start();
        System.out.println("waitFor : " + processA.waitFor());
        System.out.println("exit value : " + processA.exitValue());

        System.out.println("-- process B --");
        final var processB = new ProcessBuilder("java", "ChildB").inheritIO().start();
        System.out.println("waitFor : " + processB.waitFor());
        System.out.println("exit value : " + processB.exitValue());

        System.out.println("main : end");
    }
}

// 結果
// ↓
//> java Main
//main : start
//-- process A --
//child A : start
//child A : end
//waitFor : 0
//exit value : 0
//-- process B --
//child B : start
//child B : end
//waitFor : -100
//exit value : -100
//main : end

abstract InputStream getErrorStream ()

プロセスのエラー出力に接続された入力ストリームを返します。

public class Child {
    public static void main(String[] args) {
        System.out.println("  OUT 1");
        System.err.println("  ERR 1");
        System.out.println("  OUT 2");
        System.err.println("  ERR 2");
    }
}
public class Main {
    public static void main(String[] args) throws IOException, InterruptedException {
        System.out.println("main : start");

        final var process = new ProcessBuilder("java", "Child").start();
        try (final var reader = new BufferedReader(
                new InputStreamReader(process.getErrorStream()))) {
            reader.lines().forEach(System.out::println);
        }

        System.out.println("waitFor : " + process.waitFor());

        System.out.println("main : end");
    }
}

// 結果
// ↓
//> java Main
//main : start
//  ERR 1
//  ERR 2
//waitFor : 0
//main : end

abstract InputStream getInputStream ()

プロセスの通常の出力に接続された入力ストリームを返します。

public class Child {
    public static void main(String[] args) {
        System.out.println("  OUT 1");
        System.err.println("  ERR 1");
        System.out.println("  OUT 2");
        System.err.println("  ERR 2");
    }
}
public class Main {
    public static void main(String[] args) throws IOException, InterruptedException {
        System.out.println("main : start");

        final var process = new ProcessBuilder("java", "Child").start();
        try (final var reader = new BufferedReader(
                new InputStreamReader(process.getInputStream()))) {
            reader.lines().forEach(System.out::println);
        }

        System.out.println("waitFor : " + process.waitFor());

        System.out.println("main : end");
    }
}

// 結果
// ↓
//> java Main
//main : start
//  OUT 1
//  OUT 2
//waitFor : 0
//main : end

abstract OutputStream getOutputStream ()

プロセスの通常の入力に接続された出力ストリームを返します。

public class Child {
    public static void main(String[] args) {
        System.out.println("child : start");

        final var sc = new Scanner(System.in);
        while (sc.hasNext()) {
            final var next = sc.next();

            if ("quit".equals(next)) {
                System.out.println("  Quit!");
                break;
            }

            System.out.println("  next : " + next);
        }

        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")
                .redirectOutput(ProcessBuilder.Redirect.INHERIT).start();
        try (final var writer = new BufferedWriter(
                new OutputStreamWriter(process.getOutputStream()))) {
            writer.write("abcd");
            writer.newLine();
            writer.write("1234");
            writer.newLine();
            writer.write("quit");
            writer.newLine();
        }

        System.out.println("waitFor : " + process.waitFor());

        System.out.println("main : end");
    }
}

// 結果
// ↓
//> java Main
//main : start
//child : start
//  next : abcd
//  next : 1234
//  Quit!
//child : end
//waitFor : 0
//main : end

ProcessHandle.Info info ()

プロセスに関する情報のスナップショットを返します。

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 {
        System.out.println("main : start");

        final var process = new ProcessBuilder("java", "Child").start();
        TimeUnit.SECONDS.sleep(1);

        final var info = process.info();
        System.out.println("user : " + info.user());
        System.out.println("total cpu time : " + info.totalCpuDuration());

        System.out.println("waitFor : " + process.waitFor());

        System.out.println("main : end");
    }
}

// 結果
// ↓
//> java Main
//main : start
//user : Optional[MY-PC\xxxx]
//total cpu time : Optional[PT0.140625S]
//waitFor : 0
//main : end

final BufferedReader inputReader ()

プロセスの標準出力に接続されたBufferedReaderを返します。

public class Child {
    public static void main(String[] args) {
        System.out.println("  OUT 1");
        System.err.println("  ERR 1");
        System.out.println("  OUT 2");
        System.err.println("  ERR 2");
    }
}
public class Main {
    public static void main(String[] args) throws IOException, InterruptedException {
        System.out.println("main : start");

        final var process = new ProcessBuilder("java", "Child").start();
        try (final var reader = process.inputReader()) {
            reader.lines().forEach(System.out::println);
        }

        System.out.println("waitFor : " + process.waitFor());

        System.out.println("main : end");
    }
}

// 結果
// ↓
//> java Main
//main : start
//  OUT 1
//  OUT 2
//waitFor : 0
//main : end

final BufferedReader inputReader (Charset charset)

Charsetを使用してこのプロセスの標準出力に接続されたBufferedReaderを返します。

public class Child {
    public static void main(String[] args) {
        System.out.println("stdout.encoding = " + System.getProperty("stdout.encoding"));
        System.out.println("OUT : ○△×");
    }
}
public class Main {
    public static void main(String[] args) throws IOException, InterruptedException {
        System.out.println("main : start");

        final var charset = Charset.forName("UTF-32");

        final var process = new ProcessBuilder("java", "-Dstdout.encoding=UTF-32", "Child").start();
        try (final var reader = process.inputReader(charset)) {
            reader.lines().forEach(System.out::println);
        }

        System.out.println("waitFor : " + process.waitFor());

        System.out.println("main : end");
    }
}

// 結果
// ↓
//> java Main
//main : start
//stdout.encoding = UTF-32
//OUT : ○△×
//waitFor : 0
//main : end

boolean isAlive ()

このProcessが表すプロセスが生存しているかどうかをテストします。

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 {
        System.out.println("main : start");

        final var process = new ProcessBuilder("java", "Child").start();
        TimeUnit.SECONDS.sleep(1);

        System.out.println("isAlive : " + process.isAlive());

        System.out.println("waitFor : " + process.waitFor());
        System.out.println("isAlive : " + process.isAlive());

        System.out.println("main : end");
    }
}

// 結果
// ↓
//> java Main
//main : start
//isAlive : true
//waitFor : 0
//isAlive : false
//main : end

CompletableFuture<Process> onExit ()

プロセス終了のためのCompletableFuture<Process>を返します。

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();
        System.out.println("process : " + process);

        final var ret = process.onExit().thenApply(p -> {
            System.out.println("pid : " + p.pid());
            System.out.println("isAlive : " + p.isAlive());
            System.out.println("exitValue : " + p.exitValue());
            return p;
        }).get();
        System.out.println("ret : " + ret);

        System.out.println("main : end");
    }
}

// 結果
// ↓
//> java Main
//main : start
//process : Process[pid=6116, exitValue="not exited"]
//pid : 6116
//isAlive : false
//exitValue : 0
//ret : Process[pid=6116, exitValue=0]
//main : end

final BufferedWriter outputWriter ()

ネイティブ・エンコーディングを使用して、プロセスの通常入力に接続されたBufferedWriterを返します。

public class Child {
    public static void main(String[] args) {
        System.out.println("child : start");

        final var sc = new Scanner(System.in);
        while (sc.hasNext()) {
            final var next = sc.next();

            if ("quit".equals(next)) {
                System.out.println("  Quit!");
                break;
            }

            System.out.println("  next : " + next);
        }

        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")
                .redirectOutput(ProcessBuilder.Redirect.INHERIT).start();
        try (final var writer = process.outputWriter()) {
            writer.write("abcd");
            writer.newLine();
            writer.write("1234");
            writer.newLine();
            writer.write("quit");
            writer.newLine();
        }

        System.out.println("waitFor : " + process.waitFor());

        System.out.println("main : end");
    }
}

// 結果
// ↓
//> java Main
//main : start
//child : start
//  next : abcd
//  next : 1234
//  Quit!
//child : end
//waitFor : 0
//main : end

final BufferedWriter outputWriter (Charset charset)

Charsetを使用してプロセスの通常入力に接続されたBufferedWriterを返します。

public class Child {
    public static void main(String[] args) throws IOException {
        System.out.println("child : start");

        final var bytes = System.in.readAllBytes();
        System.out.println("  bytes : " + Arrays.toString(bytes));

        System.out.println("child : end");
    }
}
public class Main {
    public static void main(String[] args) throws IOException, InterruptedException {
        System.out.println("main : start");

        final var str = "○△×";
        final var charset = Charset.forName("UTF-32");

        System.out.println("UTF-8 : " + Arrays.toString(str.getBytes()));
        System.out.println("UTF-32 : " + Arrays.toString(str.getBytes(charset)));

        final var process = new ProcessBuilder("java", "Child")
                .redirectOutput(ProcessBuilder.Redirect.INHERIT).start();
        try (final var writer = process.outputWriter(charset)) {
            writer.write(str);
        }

        System.out.println("waitFor : " + process.waitFor());

        System.out.println("main : end");
    }
}

// 結果
// ↓
//> java Main
//main : start
//UTF-8 : [-30, -105, -117, -30, -106, -77, -61, -105]
//UTF-32 : [0, 0, 37, -53, 0, 0, 37, -77, 0, 0, 0, -41]
//child : start
//  bytes : [0, 0, 37, -53, 0, 0, 37, -77, 0, 0, 0, -41]
//child : end
//waitFor : 0
//main : end

long pid ()

プロセスのネイティブ・プロセスIDを返します。

public class Child {
    public static void main(String[] args) {
        System.out.println("child : start");

        System.out.println("  pid : " + ProcessHandle.current().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("pid : " + process.pid());

        System.out.println("waitFor : " + process.waitFor());

        System.out.println("main : end");
    }
}

// 結果
// ↓
//> java Main
//main : start
//pid : 16868
//child : start
//  pid : 16868
//child : end
//waitFor : 0
//main : end

boolean supportsNormalTermination ()

destroy()の実装が正常にプロセスを終了する場合trueを返します。destroyの実装が強制的かつ即座にプロセスを終了する場合は、falseを返します。

final var builder = new ProcessBuilder("java", "--version");
final var process = builder.start();
System.out.println(process.supportsNormalTermination()); // false

final var ret = process.waitFor();
System.out.println(ret); // 0

ProcessHandle toHandle ()

プロセスのProcessHandleを返します。

final var builder = new ProcessBuilder("java", "--version");
final var process = builder.start();
System.out.println(process); // Process[pid=9820, exitValue="not exited"]

final var handle = process.toHandle();
System.out.println(handle); // 9820

final var ret = process.waitFor();
System.out.println(ret); // 0

abstract int waitFor ()

必要な場合に、このProcessオブジェクトが表すプロセスが終了するまで現在のスレッドを待機させます。

このメソッドの使用例は、exitValue() にまとめて記載しました。
そちらのAPI使用例をご参照ください。

boolean waitFor (long timeout, TimeUnit unit)

このProcessオブジェクトが表すプロセスが終了するか、指定された待機時間が経過するまで、必要に応じて現在のスレッドを待機させます。

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 {
        System.out.println("main : start");

        final var startTime = System.nanoTime();
        final var process = new ProcessBuilder("java", "Child").start();

        System.out.println("waitFor : " + process.waitFor(2, TimeUnit.SECONDS));
        System.out.println((System.nanoTime() - startTime) / 1000000000.0 + " sec.");
        System.out.println("isAlive : " + process.isAlive());

        System.out.println("----");
        System.out.println("waitFor : " + process.waitFor(10, TimeUnit.SECONDS));
        System.out.println((System.nanoTime() - startTime) / 1000000000.0 + " sec.");
        System.out.println("isAlive : " + process.isAlive());

        System.out.println("main : end");
    }
}

// 結果
// ↓
//> java Main
//main : start
//waitFor : false
//2.0467682 sec.
//isAlive : true
//----
//waitFor : true
//5.1817541 sec.
//isAlive : false
//main : end

関連記事

ページの先頭へ