Как Java-программа может получить свой собственный идентификатор процесса? - PullRequest
328 голосов
/ 30 августа 2008

Как мне получить идентификатор моего процесса Java?

Я знаю, что есть несколько зависимых от платформы хаков, но я бы предпочел более общее решение.

Ответы [ 22 ]

302 голосов
/ 30 августа 2008

Не существует независимого от платформы способа, который гарантированно работал бы во всех реализациях jvm. ManagementFactory.getRuntimeMXBean().getName() выглядит как лучшее (самое близкое) решение. Он короткий, и , вероятно, работает в каждой широко используемой реализации.

В linux + windows возвращает значение типа 12345@hostname (12345 - идентификатор процесса). Остерегайтесь, однако, что в соответствии с документами , нет никаких гарантий относительно этого значения:

Возвращает имя, представляющее работающую виртуальную машину Java. возвращаемая строка имени может быть любой произвольной строкой и виртуальной Java реализация машины может выбрать для вставки полезной для конкретной платформы информация в возвращаемой строке имени. Каждая работающая виртуальная машина может иметь другое имя.

В Java 9 может использоваться новый API процесса :

long pid = ProcessHandle.current().pid();
107 голосов
/ 05 сентября 2011

Вы можете использовать JNA . К сожалению, пока нет общего JNA API для получения текущего идентификатора процесса, но каждая платформа довольно проста:

Windows

Убедитесь, что у вас есть jna-platform.jar тогда:

int pid = Kernel32.INSTANCE.GetCurrentProcessId();

Unix

Declare:

private interface CLibrary extends Library {
    CLibrary INSTANCE = (CLibrary) Native.loadLibrary("c", CLibrary.class);   
    int getpid ();
}

Тогда:

int pid = CLibrary.INSTANCE.getpid();

Java 9

В Java 9 новый API процесса может использоваться для получения текущего идентификатора процесса. Сначала вы берете дескриптор текущего процесса, затем запрашиваете PID:

long pid = ProcessHandle.current().pid();
53 голосов
/ 22 августа 2012

Вот метод бэкдора, который может работать не на всех виртуальных машинах, но должен работать как на Linux, так и на Windows ( оригинальный пример здесь ):

java.lang.management.RuntimeMXBean runtime = 
    java.lang.management.ManagementFactory.getRuntimeMXBean();
java.lang.reflect.Field jvm = runtime.getClass().getDeclaredField("jvm");
jvm.setAccessible(true);
sun.management.VMManagement mgmt =  
    (sun.management.VMManagement) jvm.get(runtime);
java.lang.reflect.Method pid_method =  
    mgmt.getClass().getDeclaredMethod("getProcessId");
pid_method.setAccessible(true);

int pid = (Integer) pid_method.invoke(mgmt);
36 голосов
/ 28 июня 2010

Попробуйте Сигар . очень обширные API. Лицензия Apache 2.

    private Sigar sigar;

    public synchronized Sigar getSigar() {
        if (sigar == null) {
            sigar = new Sigar();
        }
        return sigar;
    }

    public synchronized void forceRelease() {
        if (sigar != null) {
            sigar.close();
            sigar = null;
        }
    }

    public long getPid() {
        return getSigar().getPid();
    }
24 голосов
/ 07 октября 2011

Следующий метод пытается извлечь PID из java.lang.management.ManagementFactory:

private static String getProcessId(final String fallback) {
    // Note: may fail in some JVM implementations
    // therefore fallback has to be provided

    // something like '<pid>@<hostname>', at least in SUN / Oracle JVMs
    final String jvmName = ManagementFactory.getRuntimeMXBean().getName();
    final int index = jvmName.indexOf('@');

    if (index < 1) {
        // part before '@' empty (index = 0) / '@' not found (index = -1)
        return fallback;
    }

    try {
        return Long.toString(Long.parseLong(jvmName.substring(0, index)));
    } catch (NumberFormatException e) {
        // ignore
    }
    return fallback;
}

Просто позвоните, например, getProcessId("<PID>").

20 голосов
/ 16 июня 2011

Для старых JVM, в Linux ...

private static String getPid() throws IOException {
    byte[] bo = new byte[256];
    InputStream is = new FileInputStream("/proc/self/stat");
    is.read(bo);
    for (int i = 0; i < bo.length; i++) {
        if ((bo[i] < '0') || (bo[i] > '9')) {
            return new String(bo, 0, i);
        }
    }
    return "-1";
}
18 голосов
/ 26 декабря 2009

Вы можете проверить мой проект: JavaSysMon на GitHub. Он предоставляет идентификатор процесса и кучу других вещей (использование процессора, использование памяти) кроссплатформенных (в настоящее время Windows, Mac OSX, Linux и Solaris)

16 голосов
/ 26 июня 2015

Начиная с Java 9 существует метод Process.getPid (), который возвращает собственный идентификатор процесса:

public abstract class Process {

    ...

    public long getPid();
}

Чтобы получить идентификатор текущего процесса Java, можно использовать интерфейс ProcessHandle:

System.out.println(ProcessHandle.current().pid());
7 голосов
/ 30 июня 2016

Для полноты в Spring Boot есть обертка для

String jvmName = ManagementFactory.getRuntimeMXBean().getName();
return jvmName.split("@")[0];

решение. Если требуется целое число, то его можно суммировать до однострочного:

int pid = Integer.parseInt(ManagementFactory.getRuntimeMXBean().getName().split("@")[0]);

Если кто-то уже использует загрузку Spring, он / она может использовать org.springframework.boot.ApplicationPid

ApplicationPid pid = new ApplicationPid();
pid.toString();

Метод toString () печатает pid или '???'.

Предостережения, использующие ManagementFactory, уже обсуждались в других ответах.

7 голосов
/ 21 ноября 2015

В Scala:

import sys.process._
val pid: Long = Seq("sh", "-c", "echo $PPID").!!.trim.toLong

Это должно дать вам обходной путь в системах Unix до выпуска Java 9. (Я знаю, что вопрос был о Java, но поскольку у Scala нет аналогичного вопроса, я хотел оставить это для пользователей Scala, которые могут наткнуться на тот же вопрос.)

...