How to Launch a Completely Independent Process from a Java Program

How do I launch a completely independent process from a Java program?

It may help if you post a test section of minimal code needed to reproduce the problem. I tested the following code on Windows and a Linux system.

public class Main {

/**
* @param args the command line arguments
*/
public static void main(String[] args) throws Exception {
Runtime.getRuntime().exec(args[0]);
}
}

And tested with the following on Linux:

java -jar JustForTesting.jar /home/monceaux/Desktop/__TMP/test.sh

where test.sh looks like:

#!/bin/bash
ping -i 20 localhost

as well as this on Linux:

java -jar JustForTesting.jar gedit

And tested this on Windows:

java -jar JustForTesting.jar notepad.exe

All of these launched their intended programs, but the Java application had no problems exiting. I have the following versions of Sun's JVM as reported by java -version :

  • Windows: 1.6.0_13-b03
  • Linux: 1.6.0_10-b33

I have not had a chance to test on my Mac yet. Perhaps there is some interaction occuring with other code in your project that may not be clear. You may want to try this test app and see what the results are.

Java launch independent process

Your problem is due to what is called Unix job control.

Like many shells do, /bin/sh intercepts SIGHUP and SIGINT signals, and before exiting, it sends signals to some of its child processes groups, depending on its configuration and on their state (for instance, stopped background processes receive a SIGCONT).

So, when your main java app is closed, the /bin/sh shell that your app had forked is terminated, and just before exiting, it sends a SIGHUP signal to its subprocesses corresponding to the command java -jar myjar.jar.

So, the answer to your question is: just use the huponexit /bin/sh shell option to avoid killing subprocesses. They will be detached from the controlling terminal, if any, but they will not be killed.

So, replace this java -jar myjar.jar by shopt -u huponexit; java -jar myjar.jar:

ProcessBuilder processBuilder =
new ProcessBuilder(new String[] {
"su", "-s", "/bin/sh", "myuser", "-c",
"shopt -u huponexit; java -jar myjar.jar"
});
Process p = processBuilder.start();

How to execute completely independent application from Java. Like independent process

For Windows use cmd /c start ... where '...' is the command you would like to invoke.

Runtime.getRuntime().exec("cmd /c start java -cp /var/dist/test.jar main.main")

For Linux add & at the end of command to start a daemon process.

Executing a Java application in a separate process

Two hints:

System.getProperty("java.home") + "/bin/java" gives you a path to the java executable.

((URLClassLoader) Thread.currentThread().getContextClassLoader()).getURL() helps you to reconstruct the classpath of current application.

Then your EXECUTE.application is just (pseudocode):

Process.exec(javaExecutable, "-classpath", urls.join(":"), CLASS_TO_BE_EXECUTED)

How can I run a new process, and close the current program in Java?

You may want to use (on Linux)

nohup java -jar someOtherProgram.jar & 

and in Windows

start /min java -jar someOtherProgram.jar

or

javaw -jar someOtherProgram.jar 

How to run a proccess completely seperate in Java

The problem is, once the Java program finishes executing, all sub-processes are closed, also the Ruby Script.

On *nix systems (POSIX really, including Debian Linux) the process is sent a HUP signal (SIGHUP or hangup) when its' parent process ends. You can use the nohup(1) command when you start a subprocess to ignore the hangup from the child process.

Alternatively, you could potentially make use of the Ruby Signal Module and use Signal.trap(HUP) to handle it some other way.

How to run a shell script from Java and have it continue running after JVM shutdown?

When you run a process from java you are creating a shell instance which then runs the process. The shell will only exit once this process has finished even if it is being run in the background &

To run a process in headless mode you need to use the nohup command. For details, see here.

A usage could look like this:

ProcessBuilder processBuilder = new ProcessBuilder("nohup", "sh", "restart.sh");
try {
processBuilder.directory(new File(System.getProperty("user.dir")));
processBuilder.redirectErrorStream(false);
processBuilder.start();
} catch (IOException e) {
e.printStackTrace();
}

How to start independent, concurrently running Python processes from Java

First of all: Thanks for everyone who thought about my issue.

While I am a bit ashamed of the true nature of my problem I feel I should share what the issue was.

I ran my program with SLURM, a job scheduler which is also able to restrict CPU use. In my case it restricted my program to use a single CPU. Thus, more CPUs were never used by definition.

Now that I realized that I have no issues with Python concurrency at all.
To be more concrete:
The -c parameter to pass the script to the Python interpreter is not an issue here.
Also, the idea of kiran does not apply here. I have one Java Process and multiple Python processes started from the Java process and now they all consume as much CPU capacity as I would give them (I just had 3 x 300% of CPU usage from the Python processes).

So the real problem here was my assumption that this would be a Python issue. I apologize for this and will try to be clearer about my problem in the future.

Platform-independent way to start program on PATH?

ProcessBuilder does use the $PATH.

import java.io.*;

public class ProcessBuilderTest {
public static void main(String... args) throws Exception {
ProcessBuilder pb = new ProcessBuilder(args);
pb.redirectErrorStream(true);
Process p = pb.start();
int exitCode = p.waitFor();
printStream(p.getInputStream());
printStream(p.getErrorStream());
System.out.println("Exit code: " + exitCode);
}

static void printStream(InputStream stream) throws IOException {
try (BufferedReader br = new BufferedReader(new InputStreamReader(stream))) {
String line;
while ((line = br.readLine()) != null) {
System.out.println(line);
}
}
}
}

Running this on MacOS:

robert@mac:~$ java ProcessBuilderTest.java ls *.java
ProcessBuilderTest.java
Exit code: 0
robert@mac:~$ java ProcessBuilderTest.java ls *.class
ls: cannot access '*.class': No such file or directory
Exit code: 2
robert@mac:~$ java ProcessBuilderTest.java which ls
/usr/local/opt/coreutils/libexec/gnubin/ls
Exit code: 0
robert@mac:~$

Same on Linux:

robert@linux:~$ java ProcessBuilderTest.java ls *.java
ProcessBuilderTest.java
Exit code: 0
robert@linux:~$ java ProcessBuilderTest.java ls *.class
ls: cannot access '*.class': No such file or directory
Exit code: 2
robert@linux:~$ java ProcessBuilderTest.java which ls
/usr/bin/ls
Exit code: 0
robert@linux:~$

I don't use Windows, so cannot test on that.



Related Topics



Leave a reply



Submit