Java 9 : How to use Java 9 Process Api

Introduction to Java 9 Process Api

The New Java 9 Processes API will help provide

  1. Identifies the processess
  2. Control of Native processes
  3. Monitoring of processes
  4. List Children of processess
  5. Start a new Process
  6. Destroy a running process
  7. Access to the process input,output and error streams.
  8. On Exit Handle when a process is destroyed or completed.

Testing Process API operations

In this post java program we are testing the following operations

  1. List all processess running in the OS.
  2. Print the information of the current process.
  3. Create a new process and then terminate it.
  4. Do some action when the process is destroyed or completed.
  5. Try to terminate the current process.
  6. Destroy a process forcefully
  7. Get children of a process.

List all Processess

ProcessHandle.allProcesses() is a static method in ProcessHandle interface that returns Stream<ProcessHandle> object. We will iterate this stream to print the information of all the processess running.

package com.ekiras.java9.processapi;


import java.lang.ProcessHandle;
import java.util.Arrays;
import java.util.List;
import java.util.stream.Stream;

/**
 * @author ekiras
 */
public class ListAllProcesses {

    public static void main(String[] args){
        allProcesses();
    }

    public static void allProcesses() {
        System.out.println("Process list:");
        Stream<ProcessHandle> processStream = ProcessHandle.allProcesses();
        processStream.forEach(e -> printProcessInfo(e));
    }

    public static void printProcessInfo(ProcessHandle processHandle){
        System.out.println("------------------------------------------------------------------------------");
        System.out.println(" Process Id :: " + processHandle.getPid());
        System.out.println(" Process isAlive() :: " + processHandle.isAlive());
        System.out.println(" Process children :: " + processHandle.children().count());
        System.out.println(" Process supportsNormalTermination() :: " + processHandle.supportsNormalTermination());
        System.out.println(" Process Info :: " + processHandle.info().toString());

    }

}

The above code will produce the following output on console.

Process list:
---------------------------------------------------------
 Process Id :: 1
 Process isAlive() :: true
 Process children :: 0
 Process supportsNormalTermination() :: true
 Process Info :: [user: Optional[root], cmd: /bin/bash, startTime: Optional[2016-11-14T05:24:57.150Z], totalTime: Optional[PT0.02S]]
---------------------------------------------------------
 Process Id :: 15
 Process isAlive() :: true
 Process children :: 1
 Process supportsNormalTermination() :: true
 Process Info :: [user: Optional[root], cmd: /bin/bash, startTime: Optional[2016-11-14T05:25:06.670Z], totalTime: Optional[PT0.08S]]
---------------------------------------------------------
 Process Id :: 449
 Process isAlive() :: true
 Process children :: 0
 Process supportsNormalTermination() :: true
 Process Info :: [user: Optional[root], cmd: /opt/jdk-9/bin/java, args: [ListAllProcesses], startTime: Optional[2016-11-14T07:38:41.240Z], totalTime: Optional[PT0.35S]]

Current Process Information

In this example we will try to get information about the current process. For this we will use the method ProcessHandle.current() method, this will return the object ProcessHandle which can be used to get the information of the process.

import java.io.IOException;
import java.lang.ProcessHandle;

/**
 * @author ekiras
 */
public class CurrentProcess {

    public static void main(String[] args) throws IOException {
        currentProcessInfo();
    }

    public static void currentProcessInfo(){
        System.out.println("Current Process : ");
        ProcessHandle process = ProcessHandle.current();
        printProcessInfo(process);
    }


    public static void printProcessInfo(ProcessHandle processHandle){
        System.out.println("---------------------------------------------------------");
        System.out.println(" Process Id :: " + processHandle.getPid());
        System.out.println(" Process isAlive() :: " + processHandle.isAlive());
        System.out.println(" Process children :: " + processHandle.children().count());
        System.out.println(" Process supportsNormalTermination() :: " + processHandle.supportsNormalTermination());
        System.out.println(" Process Info :: " + processHandle.info().toString());

    }

}

The above code will produce the following output on console.

Current Process : 
---------------------------------------------------------
 Process Id :: 551
 Process isAlive() :: true
 Process children :: 0
 Process supportsNormalTermination() :: true
 Process Info :: [user: Optional[root], cmd: /opt/jdk-9/bin/java, args: [CurrentProcess], startTime: Optional[2016-11-14T07:45:33.440Z], totalTime: Optional[PT0.24S]]

Terminating a Process

In this example we will terminate/destroy a running process using destroy() method in the ProcessHandle interface.

To test this we have started a process to run in background. e.g

tail -F /dev/null &;

Now we will destroy this process through our code.

import java.io.IOException;
import java.lang.ProcessHandle;
import java.lang.Process;

/**
 * @author ekiras
 */
public class DestroyProcess {

    public static void main(String[] args) throws InterruptedException {
        try {
            ProcessHandle processHandle = startProcess("tail -F /dev/null").toHandle();
            printProcessInfo(processHandle);
            destroyProcess(processHandle);
            Thread.sleep(1000);
            printProcessInfo(processHandle);
        } catch (IOException e) {
            e.printStackTrace();
        }
    }

    public static void printProcessInfo(ProcessHandle processHandle){
        System.out.println("---------------------------------------------------------");
        System.out.println(" Process Id :: " + processHandle.getPid());
        System.out.println(" Process isAlive() :: " + processHandle.isAlive());
        System.out.println(" Process children :: " + processHandle.children().count());
        System.out.println(" Process supportsNormalTermination() :: " + processHandle.supportsNormalTermination());
        System.out.println(" Process Info :: " + processHandle.info().toString());

    }

    public static void destroyProcess(ProcessHandle process) throws IllegalStateException{
        System.out.println("Going to destroy Process with id :: " + process.getPid());
        process.destroy();
    }

    public static Process startProcess(String command) throws IOException {
        System.out.println("Start Process :");
        Runtime runtime = Runtime.getRuntime();
        Process process = runtime.exec(command);
        return process;
    }

}

The above code will produce the following output on console.

Start Process : 
---------------------------------------------------------
 Process Id :: 1259
 Process isAlive() :: true
 Process children :: 0
 Process supportsNormalTermination() :: true
 Process Info :: [user: Optional[root], cmd: /usr/bin/tail, args: [-F, /dev/null], startTime: Optional[2016-11-14T15:52:01.670Z], totalTime: Optional[PT0S]]
Going to destroy Process with id :: 1259
---------------------------------------------------------
 Process Id :: 1259
 Process isAlive() :: false
 Process children :: 0
 Process supportsNormalTermination() :: true
 Process Info :: []

Terminating Current Process

We cannot destroy the current Process trying to destroy the current process will throw IllegalStateException. In this example we will try to destroy/terminate the current process to see what happens when we try to destroy the current process.

import java.io.IOException;
import java.lang.ProcessHandle;

/**
 * @author ekiras
 */
public class DestroyCurrentProcess {


    public static void main(String[] args) throws IOException {
        currentProcessInfo();
    }

    public static void currentProcessInfo(){
        System.out.println("Current Process : ");
        ProcessHandle process = ProcessHandle.current();
        printProcessInfo(process);
        destroyProcess(process);
    }


    public static void printProcessInfo(ProcessHandle processHandle){
        System.out.println("---------------------------------------------------------");
        System.out.println(" Process Id :: " + processHandle.getPid());
        System.out.println(" Process isAlive() :: " + processHandle.isAlive());
        System.out.println(" Process children :: " + processHandle.children().count());
        System.out.println(" Process supportsNormalTermination() :: " + processHandle.supportsNormalTermination());
        System.out.println(" Process Info :: " + processHandle.info().toString());

    }

    public static void destroyProcess(ProcessHandle process) throws IllegalStateException{
        System.out.println("Going to destroy Process with id :: " + process.getPid());
        process.destroy();
    }

}

The above code will produce the following output on console.

Current Process : 
---------------------------------------------------------
 Process Id :: 653
 Process isAlive() :: true
 Process children :: 0
 Process supportsNormalTermination() :: true
 Process Info :: [user: Optional[root], cmd: /opt/jdk-9/bin/java, args: [DestroyCurrentProcess], startTime: Optional[2016-11-14T08:32:28.640Z], totalTime: Optional[PT0.32S]]
Going to destroy Process with id :: 653
Exception in thread "main" java.lang.IllegalStateException: destroy of current process not allowed
    at java.base/java.lang.ProcessHandleImpl.destroyProcess(ProcessHandleImpl.java:308)
    at java.base/java.lang.ProcessHandleImpl.destroy(ProcessHandleImpl.java:326)
    at DestroyCurrentProcess.destroyProcess(DestroyCurrentProcess.java:34)
    at DestroyCurrentProcess.currentProcessInfo(DestroyCurrentProcess.java:18)
    at DestroyCurrentProcess.main(DestroyCurrentProcess.java:11)

No comments :

Post a Comment