Java - Process.destroy() source code for Linux
Process management and all the like operations are done by the OS. Therefore, the JVM has to call the appropriate system call in order to destroy a process. This will, obviously, vary between operating systems.
On Linux, we have the kill
syscall to do that - or exit
if we want to terminate the currently running process. The native methods in the JDK sources are, of course, separated according to the operating system the JVM is going to run on. As noted previously, Process
has a public void destroy()
method. In the case of Linux, this method is implemented by UNIXProcess
. The destroy()
method is implemented pretty much like this:
private static native void destroyProcess(int pid);
public void destroy() {
destroyProcess(pid);
}
The native method destroyProcess()
, in turn, is defined in UNIXProcess_md.c
and looks like this:
JNIEXPORT void JNICALL
Java_java_lang_UNIXProcess_destroyProcess(JNIEnv *env, jobject junk, jint pid)
{
kill(pid, SIGTERM);
}
Where kill
is the Linux syscall, whose source is available in the Linux kernel, more precisely in the file kernel/signal.c
. It is declared as SYSCALL_DEFINE2(kill, pid_t, pid, int, sig)
.
Happy reading! :)
Killing a process using Java
If you start the process from with in your Java application (ex. by calling Runtime.exec()
or ProcessBuilder.start()
) then you have a valid Process
reference to it, and you can invoke the destroy()
method in Process
class to kill that particular process.
But be aware that if the process that you invoke creates new sub-processes, those may not be terminated (see https://bugs.openjdk.org/browse/JDK-4770092).
On the other hand, if you want to kill external processes (which you did not spawn from your Java app), then one thing you can do is to call O/S utilities which allow you to do that. For example, you can try a Runtime.exec()
on kill
command under Unix / Linux and check for return values to ensure that the application was killed or not (0 means success, -1 means error). But that of course will make your application platform dependent.
how can I kill a Linux process in java with SIGKILL Process.destroy() does SIGTERM
Not using pure Java.
Your simplest alternative is to use Runtime.exec()
to run a kill -9 <pid>
command as an external process.
Unfortunately, it is not that simple to get hold of the PID. You will either need to use reflection black-magic to access the private int pid
field, or mess around with the output from the ps
command.
UPDATE - actually, there is another way. Create a little utility (C program, shell script, whatever) that will run the real external application. Code the utility so that it remembers the PID of the child process, and sets up a signal handler for SIGTERM that will SIGKILL the child process.
The right way to kill a process in Java
If the process you want to kill has been started by your application
Then you probably have a reference to it (ProcessBuilder.start()
or Runtime.exec()
both return a reference). In this case, you can simply call p.destroy()
. I think this is the cleanest way (but be careful: sub-processes started by p
may stay alive, check Process.destroy does not kill multiple child processes for more info).
The destroyForcibly
should only be used if destroy()
failed after a certain timeout. In a nutshell
- terminate process with
destroy()
- allow process to exit gracefully with reasonable timeout
- kill it with
destroyForcibly()
if process is still alive
If the process you want to kill is external
Then you don't have much choice: you need to pass through the OS API (Runtime.exec
). On Windows, the program to call will be taskkill.exe
, while on Mac and Linux you can try kill
.
Have a look at Support for Process.destroyForcibly() and .isAlive() from Java 8 and Killing a process using Java and Code a Simple Java App to Kill Any Process After a Specified Time for more info.
Killing a Java Process object
The solution in my case, since I was writing both the parent and the child processes, was to add a ShutdownHook which halted the JVM (a simple System.exit(1) was not sufficient):
Runtime.getRuntime().addShutdownHook(new Thread() {
@Override
public void run() {
Runtime.getRuntime().halt(5);
}
});
After this, when a SIGTERM was received the process would terminate, as though it had been sent SIGKILL by the parent process.
Java tool/method to force-kill a child process
There is a leaner way to do this using Java JNA.
This works definitely for Windows and Linux, i assume that you can do the same for other platforms too.
The biggest problem of Java process handling is the lack of a method to get the process id of the process started with untime.getRuntime().exec().
Assuming you got the pid of a process, you always can start a kill -9 command in linux, or use similar ways to kill a process in windows.
Here is a way to get the process id natively for linux (borrowed from the selenium framework, :) ), and with the help of JNA this also can be done for windows (using native Windows API calls).
For this to work (for Windows) you first have to get the JNA Library at JAVA NATIVE ACCESS (JNA): Downloads or get it from maven
Look at the following code, which will get the pid of a (in this example windows) program (most of the code is actually debris to get a working java program going):
import com.sun.jna.*;
import java.lang.reflect.Field;
import java.util.logging.Level;
import java.util.logging.Logger;
public class Main {
static interface Kernel32 extends Library {
public static Kernel32 INSTANCE = (Kernel32) Native.loadLibrary("kernel32", Kernel32.class);
public int GetProcessId(Long hProcess);
}
public static void main(String[] args) {
try {
Process p;
if (Platform.isWindows())
p = Runtime.getRuntime().exec("cmd /C ping msn.de");
else if (Platform.isLinux())
p = Runtime.getRuntime().exec("cmd /C ping msn.de");
System.out.println("The PID: " + getPid(p));
int x = p.waitFor();
System.out.println("Exit with exitcode: " + x);
} catch (Exception ex) {
Logger.getLogger(Main.class.getName()).log(Level.SEVERE, null, ex);
}
}
public static int getPid(Process p) {
Field f;
if (Platform.isWindows()) {
try {
f = p.getClass().getDeclaredField("handle");
f.setAccessible(true);
int pid = Kernel32.INSTANCE.GetProcessId((Long) f.get(p));
return pid;
} catch (Exception ex) {
Logger.getLogger(Main.class.getName()).log(Level.SEVERE, null, ex);
}
} else if (Platform.isLinux()) {
try {
f = p.getClass().getDeclaredField("pid");
f.setAccessible(true);
int pid = (Integer) f.get(p);
return pid;
} catch (Exception ex) {
Logger.getLogger(Main.class.getName()).log(Level.SEVERE, null, ex);
}
}
else{}
return 0;
}
}
Hope this helps, ;)...
Process.exitValue() and Process.destroy() features
Why would it show a problem? You're trying to destroy a process that was already destroyed. The specification of
Process.destroy()
doesn't say what happens if there was nothing to destroy, so it is logical (I suppose) to assume that if there's nothing to destroy, then there's nothing to complain about. Compare withThread.join()
, which doesn't just die if the thread has already ended.The only way to kill a process is to send it a signal. On some OS's, there are other, more "violent" ways (on some platforms, for example, it is possible to simply remove the process from the OS's list of running processes. Results are undefined and it usually ends ugly), but at least with platforms that I know of, it's really all about sending signals.
Possible, indeed, that it's because it takes time to invoke
Thread.sleep()
. Try increasing the timeout value.
Java - Object runs an external process: how to stop it?
This:
new ProcessBuilder(command).start();
returns a Process
object, and if you hold a reference to it, you can call Process.destroy()
at a later time (this SO answer details the destroy()
implementation)
Related Topics
Javax.* Cannot Be Imported in My Android App
How to Check If Internet Connection Is Present in Java
How to Load a Resource from Web-Inf Directory of a Web Archive
Java Split() Method Strips Empty Strings at the End
MySQL and Jdbc with Rewritebatchedstatements=True
How to Add and Remove Elements of Enumeration at Runtime in Java
How to Convert a .Jar to an .Exe
How to Get Pid of Process I'Ve Just Started Within Java Program
What Do I Use Now That Handler() Is Deprecated
Return a Value from Asynctask in Android
Transitive Dependencies Not Resolved for Aar Library Using Gradle
How to Connect via Https Using Jsoup
Sending a JSON Http Post Request from Android
Removing Duplicates from a String in Java