Java
 Computer >> コンピューター >  >> プログラミング >> Java

Java 9のJShellを使ってプロセスのpid・info・childrenを取得し、プロセスを破棄する方法

JShellは、Java 9から導入された対話型のJavaシェルツールです。クラス、メソッド、インターフェース、列挙型(enum)などのJavaコードをコマンドライン上で手軽に実行し、その結果を即座に評価して表示することができます。

Java 9では、OSのプロセスを管理・制御するためのProcess APIが大幅に強化されました。この中核となるのがProcessHandleインターフェースです。ProcessHandleはネイティブなプロセスを識別・制御する機能を提供し、プロセスが生存しているかどうか(liveness)の確認や、プロセスの破棄(destroy)を行うメソッドを持っています。また、ProcessHandle.Infoインターフェースを使うと、特定のプロセスに関する情報のスナップショットを取得できます。

以下のコード例では、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. 現在のプロセスの取得とpidの表示

ProcessHandle.current()メソッドは、現在実行中のプロセスのProcessHandleインスタンスを返します。この例ではPID「3960」が割り当てられており、currentProcess.pid()を呼び出すことでプロセスIDを確認できます。

2. プロセス情報(info)の取得

info()メソッドを呼び出すと、ユーザー名、実行コマンドのパス、開始時刻、CPU使用時間といったプロセスの詳細情報を含むスナップショットが返されます。これらの値はOptional型でラップされている点に注意してください。

3. 特定のPIDからのProcessHandle取得

ProcessHandle.of(3960)のように、既知のPIDを指定することで、該当するプロセスのProcessHandleをOptionalとして取得できます。get()で取り出した後、再度info()を呼び出せば、そのプロセスの最新情報を確認できます。

4. 子プロセス(children)の操作と注意点

ProcessHandle.current().children()は、現在のプロセスの子プロセスをStream<ProcessHandle>として返します。ここで重要なのは、Streamは一度しか消費できないという点です。上記の例では、まずchildProc.count()でストリームを消費した後、同じストリームに対してforEach()を呼び出したため、「stream has already been operated upon or closed」というIllegalStateExceptionが発生しています。

子プロセスを正しく破棄したい場合は、ストリームを再取得するか、以下のように1つの操作にまとめて記述します。

jshell> ProcessHandle.current().children().forEach(procHandle -> {
   ...>     boolean destroyed = procHandle.destroy();
   ...>     System.out.println(destroyed ? "Terminated " + procHandle.pid() : "Could not kill process " + procHandle.pid());
   ...> });

このように、destroy()メソッドは対象プロセスの終了を試み、成功した場合はtrueを返します。ただし、他ユーザーが所有するプロセスなど、権限がない場合は破棄に失敗することもあります。

  1. Java 9のJShellでスニペットを保存・編集・削除する方法

    Java Shell、通称JShellは、Java 9で正式に導入された公式のREPL(Read-Evaluate-Print-Loop)ツールです。対話型シェルを提供し、main()メソッドを作成したり、コードを実行前にコンパイルしたりすることなく、迅速なプロトタイピングやデバッグを行うことができます。JShellは、コマンドプロンプトで「jshell」と入力するだけで簡単に起動できます。この記事では、JShellで作成したスニペット(コード断片)を保存、編集、削除する方法を解説します。スニペットを保存する(/save)スニペットのソースコードをファイルに保存するには、「/save [-al

  2. Java 9のJShellでクラスとオブジェクトを作成する方法をわかりやすく解説

    JShellは、Java 9で新たに導入されたJavaシェルツールです。Java初の公式REPL(Read-Evaluate-Print-Loop:読み込み・評価・出力・繰り返し)アプリケーションとして提供されています。このツールを活用すると、ステートメント、ループ、式などの簡単なJavaプログラムやロジックを、その場で実行・評価することが可能です。Java REPLはコマンドプロンプト上で手軽なプログラミング環境を提供し、入力されたコードを読み取り、評価し、その結果を出力します。コンパイルやクラスファイルの作成を意識することなく、対話形式でJavaコードを試せるのが大きな特徴です。以下の例で