Several methods of Java process calling external program

Posted by jswash on Sun, 09 Jan 2022 16:01:20 +0100

Several methods of Java process calling external program

The floor sweeper has recorded the notes of controlling the remote server through the Java program and then calling the specified program. Use java code to connect to the software in the Windows server in the LAN and execute instructions

Now I will briefly summarize several methods of Java process calling external programs. During this period, I will simply look at the source code.

Executing system commands through Java is the same as executing Shell commands in cmd or on Linux terminals. The most typical usage is using runtime, getruntime() Exec (command) or new processbuilder (cmdarray) start().

1 Runtime

The Runtime class is the Runtime environment for Java programs. You cannot new a Runtime object. You can only get the reference of the current Runtime object through the getRuntime() method. You can then call the Runtime method to view and modify the state of the Java virtual machine.

As can be seen from the figure above, the Runtime class does not provide us with a constructor, so we can't new a Runtime object. This is a simple single example. You can see that its getRuntime() method does not perform parallel processing, but only one Runtime object is allowed in the whole environment.

The difference between Runtime and ProcessBuilder is that the command form when starting the child process is different, Runtime getRuntime. Exec () can write commands and parameters in a String separated by spaces. ProcessBuilder is the parameter of the constructor, passing a list or array composed of commands and parameters.

The main methods of the Runtime class are as follows:

  1. The exec method receives a command and then executes it. Through this method, you can execute the same command as used in cmd. For example, runtime getRuntime(). Exec ("LS") has the same effect as executing ls in cmd.
  2. freeMemory() can view how much free memory is left in the current virtual machine memory.
  3. totalMemory() can view the total memory used by the current virtual machine.
  4. maxMemory() can check the maximum memory that the JVM can eventually use.
  5. availableProcessors() can see how many processors the machine has, that is, how many cores the native processor is.
  6. The exit(int) method can exit the running of the current Java program, system The exit(int) method simply calls the runtime exit(int) method to exit the running.

The above will also be used when we do distributed parallelization programming and view computer parameters.

@Test
public void test2() throws IOException {
    Runtime.getRuntime().exec("java -version");
    System.out.println(Runtime.getRuntime().freeMemory());
    System.out.println(Runtime.getRuntime().totalMemory());
    System.out.println(Runtime.getRuntime().maxMemory());
}

2 Process

Process is an abstract class. Its main methods are as follows:

  1. waitFor() is to make the current main process wait for the execution of the child process pointed to by the process to complete.
  2. exitValue() can view the exit value of the child process pointed to by process after execution. 0 means the end of normal operation.
  3. destroy() and destroyForcibly() can terminate the operation of the process sub process. The latter is forced termination. The former is related to the specific implementation of the platform termination process.

Via runtime getRuntime(). exe(...) You can create a local Process to execute the incoming command. This method returns an instance of Process:

Process points to a local process. Compared with the main process, the process points to is called a child process. Is is to obtain the output information of the child process.

Why InputStream when it is to obtain output information? Compared with the main Process, the output of the child Process is the input of the main Process, so it is InputStream. vice verse. If you want to pass parameters or input information to the child Process, you should use OutputStream. However, it is not recommended to use the Process introduced by java 1.0, but use the Process builder of java 5.0 instead.

3 ProcessBuilder

ProcessBuilder is introduced in java 5.0. The start() method returns an instance of Process, such as:

private static boolean processMp4(String oldfilepath) {
    if (!checkfile(inputPath)) {
        log.error(oldfilepath + "Not a file path");
        return false;
    }
    List<String> command = new ArrayList<String>();
    command.add("ffmpeg");
    command.add("-i");
    command.add(oldfilepath);
    command.add("-c:v");
    command.add("libx264");
    command.add("-mbd");
    command.add("0");
    command.add("-c:a");
    command.add("aac");
    command.add("-strict");
    command.add("-2");
    command.add("-pix_fmt");
    command.add("yuv420p");
    command.add("-movflags");
    command.add("faststart");
    command.add(outputPath + "a.mp4");
    try {
        Process videoProcess = new ProcessBuilder(command).redirectErrorStream(true).start();
        new PrintStream(videoProcess.getErrorStream()).start();
        new PrintStream(videoProcess.getInputStream()).start();
        videoProcess.waitFor();
        return true;
    } catch (Exception e) {
        e.printStackTrace();
        return false;
    }
}

Creating ProcessBuilder does not need to go through Runtime, but Runtime getRimtime(). Exec (string) calls the construction method of ProcessBuilder to create a child process and execute it.

The construction method of ProcessBuilder receives an array of command parameters. The first element represents the system command to be executed, and the following element represents the parameters to be passed to the command.

Call After the start() method runs, you can get the Process reference of the child Process, and then you can call the method of Process for processing.

Running time getRuntime(). Exec () or processbuilder (array) After the sub Process process is created by start(), the output information and error information of the sub Process must be taken away in time. Otherwise, the output information flow and error information flow are likely to be filled up because of too much information, which eventually leads to the blocking of the sub Process and the execution of the sub Process.

For example, in the code of the floor sweeper above, the thread is used to take the output information and error information in time:

new PrintStream(videoProcess.getErrorStream()).start();
/**
 * Running time getRuntime(). Exec () or processbuilder (array) After start() creates the child Process,
 * The output information and error information of the sub process must be taken away in time, otherwise the output information flow and error information flow may be filled up due to too much information,
 * Eventually, the child process is blocked and cannot be executed.
 */
class PrintStream extends Thread {
    InputStream is = null;
    public PrintStream(InputStream is)
    {
        this.is = is;
    }
    @Override
    public void run() {
        try{
            while(true) {
                int ch = is.read();
                if(ch != -1) {
                    System.out.print((char)ch);
                } else {
                    break;
                }
            }
        }
        catch (Exception e){
            e.printStackTrace();
        }
    }
}

Topics: Runtime