Tuesday, January 7, 2014

How to Force Kill a Process in Java

In Java, there is no easy way to force a termination of a process spawned in Java. Calling Process.destroy() does not guarantee that the process will be terminated. Although Java 8 might fix this with Process.destroyForcibly(), if you still use older versions of Java, you are out of luck. Below is a not-so-portable solution to terminate a process on Linux and Windows using Java Native Runtime. You could also use JNA or JNI to invoke the OS native API.
package test;

import java.lang.reflect.Field;

import jnr.ffi.LibraryLoader;
import jnr.ffi.Pointer;
import jnr.ffi.Runtime;

public class Test {
    public static interface Kernel32 {
        boolean TerminateProcess(Pointer handle, int exitCode);
    }
    
    public static interface Posix {
        int kill(int pid, int sig);
    }
    
    public static void main(String[] args) throws Exception {
        ProcessBuilder pb = new ProcessBuilder(args[0]);
        Process p = pb.start();
        System.out.println("Sleeping for 5 seconds");
        Thread.sleep(5000);
        p.destroy();
        if (System.getProperty("os.name").toLowerCase().startsWith("win")) {
            if (p.getClass().getName().equals("java.lang.Win32Process") ||
                p.getClass().getName().equals("java.lang.ProcessImpl")) {
                Field f = p.getClass().getDeclaredField("handle");
                f.setAccessible(true);
                long handle = f.getLong(p);
                
                System.out.println("Killing process");
                Pointer ptr = Pointer.wrap(Runtime.getSystemRuntime(), handle);
                int exitCode = 0;
                Kernel32 kernel32 = LibraryLoader.create(Kernel32.class).load("Kernel32");
                kernel32.TerminateProcess(ptr, exitCode);
            }
        } else {
            if (p.getClass().getName().equals("java.lang.UNIXProcess")) {
                Field f = p.getClass().getDeclaredField("pid");
                f.setAccessible(true);
                int pid = f.getInt(p);
                
                System.out.println("Killing process");
                Posix posix = LibraryLoader.create(Posix.class).load("c");
                posix.kill(pid, 9);
            }
        }
    }
}

No comments:

Post a Comment