Use Cases for the Java Process API
These are probably some ways how we are using the Java Process API:
- To Install, configure or to communicate to other programs from Java: For example, I implemented a Java Installer to install the WebSphere Application Server into the system, and then I configure it by running a script coded in Jython executed the wsadmin tool.
- To install specific Operating System stuff. I didn’t find any other simpler way to install Windows start menu items from Java other than by doing it in a VBScript program.
- In my opinion, the Java Process API is in general used to integrate Java with other programs or processes. For example. I made a game in Blender and I implemented a launcher in Java. So, from Java I am calling the blender.exe passing the game.blender file as argument.
Known Problems and Workarounds
- There are common issues in Windows when invoking commands which have spaces or stream redirections. The solution is to use instead the “cmd /C” command. This oracle blog talks about this. There is also an Apache commons-exec library apparently solving the same issues, but its kind of abandoned project.
- Another issue when running processes is how to read from standard output and error streams properly. The solution is basically creating separate threads for reading the streams so the process don’t get stucked. There is an elegant solution in this blog.
- On the other “side” (literally), if we want to kill a Java Process from the Operating System we may use the Java jps command to get the PID. Then, for instance, we can use kill -9 to kill it.
- Finally. Sometimes when calling a Process it ends up hanging. Hopefully the Java 9 implementation will be more stable about this issue.
Java 9 Specification
Getting started with Java 9
- Download the Java 9 version from https://jdk9.java.net/download/.
- Install java 9 on folder /usr/lib/jvm/java-9-oracle
- Check installation by running /usr/lib/jvm/java-9-oracle/bin/java -version
Get PID of current and created processes
System.out.println("Running java process with PID " + ProcessHandle.current().getPid()+ ". Parent: " + ProcessHandle.current().parent().get().getPid());
Process pr = Runtime.getRuntime().exec(cmdArray);
System.out.println("Create Process with PID "+pr.getPid());
Enumerate Process List
ProcessHandle.allProcesses().forEach(e -> System.out.println(e.getPid() + " " + e.info().commandLine()));
Deal with Process Trees
In this case, we want to deploy a process tree in order to kill everything afterwards. For this, we can implement a Java Process that creates the same Java Process recursively, finally we kill it.
Process ptree = RunHelper.exec(java, output, "-cp", cp, RecursiveJavaProcess.class.getName(), "3");
Compile & execute!
$ cd src/test/java
$ /usr/lib/jvm/java-9-oracle/bin/javac org/andresoviedo/tests/java9/process/NewJava9ProcessAPI.java
$ /usr/lib/jvm/java-9-oracle/bin/javac org/andresoviedo/tests/java9/process/RecursiveJavaProcess.java
$ /usr/lib/jvm/java-9-oracle/bin/java org.andresoviedo.tests.java9.process.NewJava9ProcessAPI
Although I would like to know more real complex use cases to further evaluate the API, so far the promised features seems to work. Anyway, I am wondering what else would be nice to have for the future in the API. Probably a way to manage the process priority? I don’t know. For me, the API looks quite complete for now. I hope you like the new features.
Feel free to leave your comments. Thank you for reading me :)