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
Why Is String Immutable in Java
In Java, What Are the Advantages of Streams Over Loops
Differencebetween a Javabean and a Pojo
What Is Simplest Way to Read a File into String
Should We @Override an Interface's Method Implementation
When Would You Call Java's Thread.Run() Instead of Thread.Start()
Log4J Redirect Stdout to Dailyrollingfileappender
Spring Boot - Inject Map from Application.Yml
What's the Difference Between <> and <? Extends Object> in Java Generics
Printing All Variables Value from a Class
Convert Boolean to Int in Java
How to Calculate the Intersection of Two Sets
Simple Way to Find If Two Different Lists Contain Exactly the Same Elements
Eclipse Returns Error Message "Java Was Started But Returned Exit Code = 1"
Does a Finally Block Always Run
Spring Configuration Xml Schema: with or Without Version
Spring: How to Inject an Httpservletrequest into a Request-Scoped Bean