[Java] [Implementation] Java Process class
version
java 8
API
First, let’s take a look at the
Process class from Java API Docs.
Class Process java.lang.Object Java.lang.Process
The ProcessBuilder.start() and Runtime.exec methods create a native process and return an instance of a subclass of Process, which you can use to control and get information about it. The Process class provides methods for inputting from the process, outputting to the process, waiting for the process to complete, checking the process termination status, and destroying (terminating) the process. For example, a native windowing process, a daemon process, a Win16/DOS process under Microsoft Windows, or a shell script process.
By default, the created subprocess does not have its own terminal or console. All its standard I/O (i.e. standard input, standard output, and standard error) processing is redirected to the parent process, but the methods getOutputStream(), getInputStream(), and getErrorStream() can be used to access that information. Use the stream that is retrieved with. The parent process uses these streams to send input to and get output from the subprocess. Some native platforms have a limited buffer size for standard I/O streams, so if a subprocess’s input stream write or stream output read fails, the subprocess is blocked or deadlocked. May be.
If desired, you can also use the methods of the ProcessBuilder class to redirect the input and output of the subprocess.
If there are no more references to the Process object, the subprocess will not be terminated and will continue to run asynchronously.
The execution of the process represented by the Process object does not have to be asynchronous or parallel with the Java process that owns the Process object.
Precautions
deadlock
Some native platforms have a limited buffer size for standard I/O streams, so if a subprocess’s input stream write or stream output read fails, the subprocess will block or deadlock. It may be in a state.
The most important thing to watch out for is the possibility of deadlock.
bad.java
Process p = Runtime.getRuntime().exec("cmd /c dir"); // Make the current thread wait until the process is finished. // ★★★ The process is blocked if the standard output stream has a lot of output ★★★ p.waitFor();
stream
The ProcessBuilder.start() and Runtime.exec methods create a native process and return an instance of a subclass of Process, which you can use to control and get information about it.
It provides ways to control the process and get information.
To avoid the above deadlock, read the standard output stream and standard error stream from the JVM
getInputStreamand
getErrorStream method can be used
demo.java
try (BufferedReader br = new BufferedReader(new InputStreamReader(p.getInputStream())))) ( String line = null; while ((line = br.readLine()) != null) { // You don't have to output } } catch (IOException e) { e.printStackTrace(); }
Process termination
If there are no more references to the Process object, the subprocess will not be terminated and will continue to run asynchronously.
Given the description in the API Docs, after using the Process object, I should be able to free the Process object from java’s GC, but just differently, I’m still running. So it’s better to call the destroy() method.
bad.java
Process p = Runtime.getRuntime().exec("cmd /c dir"); // p.destroy(); ★★★ Do not finish ★★★
Sample code
Process sample
MainTest.java
import java.io.BufferedReader; import java.io.IOException; import java.io.InputStream; import java.io.InputStreamReader; import java.io.UnsupportedEncodingException; //sample public class MainTest { public static void main(String[] args) throws IOException, InterruptedException { Process p = Runtime.getRuntime().exec("cmd /c cd bin && java ProcessTest"); // output stream new StreamThread(p.getInputStream(), "OUTPUT").start(); // error stream new StreamThread(p.getErrorStream(), "ERROR").start(); // get process execution result int result = p.waitFor(); p.destroy(); // output data System.out.println(" ■ execution result code: "+ result); } } // stream thread class StreamThread extends Thread { private InputStream in; private String type; public StreamThread(InputStream in, String type) { this.in = in; this.type = type; } @Override public void run() { try (BufferedReader br = new BufferedReader(new InputStreamReader(in, "MS932")))) { String line = null; while ((line = br.readLine()) != null) { // output logs System.out.println(type + ">" + line); } } catch (UnsupportedEncodingException e) { e.printStackTrace(); } catch (IOException e) { e.printStackTrace(); } } }
Child process to call (for testing)
ProcessTest.java
public class ProcessTest { public static void main(String[] args) { for (int i = 1; i <= 1000; i++) { // standard output System.out.println("This is standard output:" + i + "number."); // standard error System.err.println("This is standard error: "+ i + "number."); } } }