All Downloads are FREE. Search and download functionalities are using the official Maven repository.

com.ovea.system.util.ProcUtils Maven / Gradle / Ivy

There is a newer version: 1.7.ga
Show newest version
/**
 * Copyright (C) 2011 Ovea 
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 * http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */
package com.ovea.system.util;

import com.sun.jna.Platform;
import com.sun.jna.Pointer;
import com.sun.jna.platform.win32.Kernel32;
import com.sun.jna.platform.win32.WinNT;
import org.hyperic.jni.ArchNotSupportedException;
import org.hyperic.sigar.Sigar;
import org.hyperic.sigar.SigarException;
import org.hyperic.sigar.SigarLoader;

import java.io.*;
import java.lang.management.ManagementFactory;
import java.lang.reflect.Field;
import java.lang.reflect.Method;
import java.nio.channels.FileChannel;
import java.nio.channels.FileLock;
import java.util.regex.Matcher;
import java.util.regex.Pattern;

/**
 * @author Mathieu Carbou ([email protected])
 */
public final class ProcUtils {

    private ProcUtils() {
    }

    public static long pid(Process process) {
        String cName = process.getClass().getName();
        if (cName.equals("java.lang.UNIXProcess")) {
            /* get the PID on unix/linux systems */
            try {
                Field f = process.getClass().getDeclaredField("pid");
                f.setAccessible(true);
                return f.getInt(process);
            } catch (Throwable e) {
                throw new IllegalStateException("Unable to recover PID from Unix process" + process);
            }
        } else if (cName.equals("java.lang.ProcessImpl") || cName.equals("java.lang.Win32Process")) {
            /* determine the pid on windows plattforms */
            try {
                Field f = process.getClass().getDeclaredField("handle");
                f.setAccessible(true);
                long handl = f.getLong(process);
                WinNT.HANDLE handle = new WinNT.HANDLE();
                handle.setPointer(Pointer.createConstant(handl));
                return Kernel32.INSTANCE.GetProcessId(handle);
            } catch (Throwable e) {
                throw new IllegalStateException("Unable to recover PID from Windows process" + process);
            }
        } else {
            throw new IllegalArgumentException("Process type not supported: " + process.getClass().getName());
        }
    }

    public static long currentPID() {
        // lazy instanciation
        return RuntimePID.get();
    }

    public static void kill(Process process) {
        long pid = pid(process);
        String cName = process.getClass().getName();
        if (cName.equals("java.lang.UNIXProcess")) {
            /* get the PID on unix/linux systems */
            try {
                Method destroyProcess = process.getClass().getDeclaredMethod("destroyProcess", int.class);
                destroyProcess.setAccessible(true);
                destroyProcess.invoke(null, (int) pid);
            } catch (Throwable e) {
                kill(pid);
            }
        } else if (cName.equals("java.lang.ProcessImpl") || cName.equals("java.lang.Win32Process")) {
            /* determine the pid on windows plattforms */
            try {
                Field f = process.getClass().getDeclaredField("handle");
                f.setAccessible(true);
                Method destroyProcess = process.getClass().getDeclaredMethod("terminateProcess", long.class);
                destroyProcess.setAccessible(true);
                destroyProcess.invoke(null, f.getLong(process));
            } catch (Throwable e) {
                kill(pid);
            }
        } else {
            throw new IllegalArgumentException("Process type not supported: " + process.getClass().getName());
        }
    }

    public static void kill(long pid) {
        if (Platform.isWindows() || Platform.isWindowsCE()) {
            WinNT.HANDLE handle = Kernel32.INSTANCE.OpenProcess(0x0001, true, (int) pid);
            Kernel32.INSTANCE.TerminateProcess(handle, 0);
        } else {
            UnixKiller.kill(pid);
        }
    }

    private static final class RuntimePID {
        private static final long pid;

        static {
            /* tested on: */
            /* - windows xp sp 2, java 1.5.0_13 */
            /* - mac os x 10.4.10, java 1.5.0 */
            /* - debian linux, java 1.5.0_13 */
            /* all return pid@host, e.g 2204@antonius */
            String processName = ManagementFactory.getRuntimeMXBean().getName();
            Matcher matcher = Pattern.compile("^([0-9]+)@.+$", Pattern.CASE_INSENSITIVE).matcher(processName);
            if (matcher.matches()) {
                pid = Long.parseLong(matcher.group(1));
            } else {
                throw new IllegalStateException("Unable to recover PID from process identifier: " + processName);
            }
        }

        public static long get() {
            return pid;
        }
    }

    private static final class UnixKiller {

        private static final String SIGAR_VERSION = "-" + System.getProperty("ovea.system.sigar.version", "1.6.4");
        private static final Sigar SIGAR;

        static {
            try {
                File tmp = new File(System.getProperty("java.io.tmpdir"), "ovea-system-sigar");
                if (!tmp.exists()) {
                    tmp.mkdirs();
                }
                SigarLoader loader = new SigarLoader(Sigar.class);
                File lib = new File(tmp, loader.getLibraryName());
                File lockFile = new File(lib + ".lock");
                FileChannel channel = null;
                FileLock lock = null;

                try {
                    channel = new RandomAccessFile(lockFile, "rw").getChannel();
                    lock = channel.lock();
                    if (!lib.exists()) {
                        InputStream in = null;
                        OutputStream out = null;
                        try {
                            String name = loader.getLibName();
                            if (name == null) {
                                name = loader.getDefaultLibName();
                            }
                            name = SigarLoader.getLibraryPrefix() + name + SIGAR_VERSION + SigarLoader.getLibraryExtension();
                            in = loader.getClassLoader().getResourceAsStream(name);
                            if (in == null) {
                                throw new IllegalStateException("SIGAR library " + name + " not found in classpath");
                            }
                            in = new BufferedInputStream(in);
                            out = new BufferedOutputStream(new FileOutputStream(lib));
                            byte[] buffer = new byte[8192];
                            int c;
                            while ((c = in.read(buffer)) != -1) {
                                out.write(buffer, 0, c);
                            }
                        } finally {
                            if (out != null)
                                try {
                                    out.close();
                                } catch (IOException ignored) {
                                }
                            if (in != null)
                                try {
                                    in.close();
                                } catch (IOException ignored) {
                                }
                        }
                    }
                } catch (IOException e) {
                    throw new RuntimeException(e.getMessage(), e);
                } finally {
                    if (lock != null)
                        try {
                            lock.release();
                        } catch (IOException ignored) {
                        }
                    if (channel != null)
                        try {
                            channel.close();
                        } catch (IOException ignored) {
                        }
                    lockFile.delete();
                }
                System.setProperty(loader.getPackageName() + ".path", tmp.getAbsolutePath());
                SIGAR = new Sigar();
                Sigar.load();
            } catch (ArchNotSupportedException e) {
                throw new RuntimeException(e.getMessage(), e);
            } catch (SigarException e) {
                throw new RuntimeException(e.getMessage(), e);
            }
            Runtime.getRuntime().addShutdownHook(new Thread() {
                @Override
                public void run() {
                    SIGAR.close();
                }
            });
        }

        public static void kill(long pid) {
            int signal = Sigar.getSigNum("SIGTERM");
            try {
                SIGAR.kill(pid, signal);
            } catch (SigarException e) {
                throw new RuntimeException(e.getMessage(), e);
            }
        }
    }
}




© 2015 - 2025 Weber Informatics LLC | Privacy Policy