Frage

Wie erhalte ich die ID meines Java-Prozesses?

Ich weiß, dass es mehrere plattformabhängige Hacks gibt, aber ich würde eine allgemeinere Lösung bevorzugen.

War es hilfreich?

Lösung

Es gibt keine plattformunabhängige Möglichkeit, die garantiert in allen JVM-Implementierungen funktioniert.ManagementFactory.getRuntimeMXBean().getName() scheint die beste (nächstliegende) Lösung zu sein.Es ist kurz und wahrscheinlich Funktioniert in jeder Implementierung im breiten Einsatz.

Unter Linux+Windows gibt es einen Wert zurück wie 12345@hostname (12345 wobei es sich um die Prozess-ID handelt).Seien Sie jedoch vorsichtig laut den Dokumenten, es gibt keine Garantien für diesen Wert:

Gibt den Namen zurück, der die ausgeführte Java Virtual Machine darstellt.Die zurückgegebene Namenszeichenfolge kann eine beliebige Zeichenfolge sein, und eine Implementierung von Java Virtual Machine kann die plattformspezifische nützliche Informationen in der zurückgegebenen Namenszeichenfolge einbetten.Jede laufende virtuelle Maschine kann einen anderen Namen haben.

In Java 9 das neue Prozess-API kann verwendet werden:

long pid = ProcessHandle.current().pid();

Andere Tipps

Du könntest benutzen JNA.Leider gibt es noch keine gemeinsame JNA-API, um die aktuelle Prozess-ID zu erhalten, aber jede Plattform ist ziemlich einfach:

Windows

Stell sicher dass du hast jna-platform.jar Dann:

int pid = Kernel32.INSTANCE.GetCurrentProcessId();

Unix

Erklären:

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

Dann:

int pid = CLibrary.INSTANCE.getpid();

Java 9

Unter Java 9 das neue Prozess-API kann verwendet werden, um die aktuelle Prozess-ID abzurufen.Zuerst greifen Sie auf den aktuellen Prozess zu und fragen dann die PID ab:

long pid = ProcessHandle.current().pid();

Hier ist eine Backdoor-Methode, die könnte Funktioniert nicht mit allen VMs, sollte aber sowohl unter Linux als auch unter Windows funktionieren (Originalbeispiel hier):

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);

Versuchen Sigar .sehr umfangreiche APIs.Apache 2-Lizenz.

    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();
    }

Die folgende Methode versucht, die PID daraus zu extrahieren 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;
}

Ruf einfach an getProcessId("<PID>"), zum Beispiel.

Für ältere JVM unter 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";
}

Sie können sich mein Projekt ansehen: JavaSysMon auf GitHub.Es stellt Prozess-IDs und eine Reihe anderer Dinge (CPU-Nutzung, Speichernutzung) plattformübergreifend bereit (derzeit Windows, Mac OSX, Linux und Solaris).

Seit Java 9 gibt es eine Methode Process.getPid(), die die native ID eines Prozesses zurückgibt:

public abstract class Process {

    ...

    public long getPid();
}

Um die Prozess-ID des aktuellen Java-Prozesses zu erhalten, kann man die verwenden ProcessHandle Schnittstelle:

System.out.println(ProcessHandle.current().pid());

In Scala:

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

Dies sollte Ihnen auf Unix-Systemen einen Workaround bieten, bis Java 9 veröffentlicht wird.(Ich weiß, die Frage bezog sich auf Java, aber da es keine entsprechende Frage für Scala gibt, wollte ich sie Scala-Benutzern überlassen, die möglicherweise auf dieselbe Frage stoßen.)

Der Vollständigkeit halber gibt es einen Wrapper Frühlingsstiefel für die

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

Lösung.Wenn eine Ganzzahl erforderlich ist, kann diese in einem Einzeiler zusammengefasst werden:

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

Wenn jemand Spring Boot bereits verwendet, könnte er/sie es verwenden org.springframework.boot.ApplicationPid

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

Die toString()-Methode gibt die PID oder „???“ aus.

Vorbehalte bei der Verwendung der ManagementFactory werden bereits in anderen Antworten besprochen.

public static long getPID() {
    String processName = java.lang.management.ManagementFactory.getRuntimeMXBean().getName();
    if (processName != null && processName.length() > 0) {
        try {
            return Long.parseLong(processName.split("@")[0]);
        }
        catch (Exception e) {
            return 0;
        }
    }

    return 0;
}

Das Neueste, was ich gefunden habe, ist, dass es eine gibt Systemeigenschaft angerufen sun.java.launcher.pid Das ist zumindest unter Linux verfügbar.Mein Plan ist es, das zu verwenden und wenn es nicht gefunden wird, das zu verwenden JMX bean.

java.lang.management.ManagementFactory.getRuntimeMXBean().getName().split("@")[0]

Es hängt davon ab, wo Sie die Informationen suchen.

Wenn Sie Informationen über die Konsole suchen, können Sie den Befehl jps verwenden.Der Befehl liefert eine ähnliche Ausgabe wie der Unix-Befehl ps und ist, glaube ich, seit 1.5 im JDK enthalten

Wenn Sie auf den Prozess achten, ist RuntimeMXBean (wie von Wouter Coekaerts gesagt) wahrscheinlich die beste Wahl.Die Ausgabe von getName() unter Windows mit Sun JDK 1.6 u7 hat die Form [PROCESS_ID]@[MACHINE_NAME].Sie könnten jedoch versuchen, jps auszuführen und das Ergebnis daraus zu analysieren:

String jps = [JDK HOME] + "\\bin\\jps.exe";
Process p = Runtime.getRuntime().exec(jps);

Bei Ausführung ohne Optionen sollte die Ausgabe die Prozess-ID gefolgt vom Namen sein.

Basierend auf Ashwin Jayaprakashs Antwort (+1) über den lizenzierten Apache 2.0 SIGAR, hier ist, wie ich es verwende, um nur die PID des aktuellen Prozesses zu erhalten:

import org.hyperic.sigar.Sigar;

Sigar sigar = new Sigar();
long pid = sigar.getPid();
sigar.close();

Auch wenn es nicht auf allen Plattformen funktioniert, funktioniert es auf allen Linux, Windows, OS X und verschiedene Unix-Plattformen, wie hier aufgeführt.

Dies ist der Code, den JConsole und möglicherweise auch JPS und VisualVM verwenden.Es nutzt Klassen vonsun.jvmstat.monitor.* Paket, von tool.jar.

package my.code.a003.process;

import sun.jvmstat.monitor.HostIdentifier;
import sun.jvmstat.monitor.MonitorException;
import sun.jvmstat.monitor.MonitoredHost;
import sun.jvmstat.monitor.MonitoredVm;
import sun.jvmstat.monitor.MonitoredVmUtil;
import sun.jvmstat.monitor.VmIdentifier;


public class GetOwnPid {

    public static void main(String[] args) {
        new GetOwnPid().run();
    }

    public void run() {
        System.out.println(getPid(this.getClass()));
    }

    public Integer getPid(Class<?> mainClass) {
        MonitoredHost monitoredHost;
        Set<Integer> activeVmPids;
        try {
            monitoredHost = MonitoredHost.getMonitoredHost(new HostIdentifier((String) null));
            activeVmPids = monitoredHost.activeVms();
            MonitoredVm mvm = null;
            for (Integer vmPid : activeVmPids) {
                try {
                    mvm = monitoredHost.getMonitoredVm(new VmIdentifier(vmPid.toString()));
                    String mvmMainClass = MonitoredVmUtil.mainClass(mvm, true);
                    if (mainClass.getName().equals(mvmMainClass)) {
                        return vmPid;
                    }
                } finally {
                    if (mvm != null) {
                        mvm.detach();
                    }
                }
            }
        } catch (java.net.URISyntaxException e) {
            throw new InternalError(e.getMessage());
        } catch (MonitorException e) {
            throw new InternalError(e.getMessage());
        }
        return null;
    }
}

Es gibt einige Haken:

  • Der tool.jar ist eine Bibliothek, die mit Oracle JDK, aber nicht mit JRE verteilt wird!
  • Du kannst nicht bekommen tool.jar aus dem Maven-Repo;Die Konfiguration mit Maven ist etwas schwierig
  • Der tool.jar Enthält wahrscheinlich einen plattformabhängigen (nativen?) Code, sodass er nicht leicht ausverteilbar ist
  • Es wird davon ausgegangen, dass alle (lokal) laufenden JVM-Apps „überwachbar“ sind.Es sieht so aus, dass Java 6 alle Apps im Allgemeinen sind (es sei denn, Sie konfigurieren aktiv das Gegenteil)
  • Es funktioniert wahrscheinlich nur für Java 6+
  • Eclipse veröffentlicht nicht die Hauptklasse, sodass Sie Eclipse PID nicht leicht in maitoredVmutil fördern können?

AKTUALISIEREN:Ich habe gerade noch einmal überprüft, ob JPS diese Methode verwendet, nämlich die Jvmstat-Bibliothek (Teil von tool.jar).Es besteht also keine Notwendigkeit, JPS als externen Prozess aufzurufen. Rufen Sie die Jvmstat-Bibliothek direkt auf, wie mein Beispiel zeigt.Auf diese Weise können Sie auch eine Liste aller JVMs abrufen, die auf localhost ausgeführt werden.Siehe JPS Quellcode:

Du kannst es versuchen getpid() In JNR-Posix.

Es verfügt über einen Windows POSIX-Wrapper, der getpid() von libc aus aufruft.

Ich weiß, dass dies ein alter Thread ist, aber ich wollte darauf hinweisen, dass die API zum Abrufen der PID (sowie für andere Manipulationen des Java-Prozesses zur Laufzeit) zur Process-Klasse in JDK 9 hinzugefügt wird: http://openjdk.java.net/jeps/102

Ich habe eine Lösung gefunden, die vielleicht eher ein Grenzfall ist, und ich habe sie nicht auf einem anderen Betriebssystem als Windows 10 ausprobiert, aber ich denke, sie ist eine Beachtung wert.

Wenn Sie feststellen, dass Sie mit arbeiten J2V8 und nodejs können Sie eine einfache Javascript-Funktion ausführen, die Ihnen die PID des Java-Prozesses zurückgibt.

Hier ist ein Beispiel:

public static void main(String[] args) {
    NodeJS nodeJS = NodeJS.createNodeJS();
    int pid = nodeJS.getRuntime().executeIntegerScript("process.pid;\n");
    System.out.println(pid);
    nodeJS.release();
}

Ergänzung zu anderen Lösungen.

mit Java 10, zu bekommen process id

final RuntimeMXBean runtime = ManagementFactory.getRuntimeMXBean();
final long pid = runtime.getPid();
out.println("Process ID is '" + pid);

Hier ist meine Lösung:

public static boolean isPIDInUse(int pid) {

        try {

            String s = null;
            int java_pid;

            RuntimeMXBean rt = ManagementFactory.getRuntimeMXBean();
            java_pid = Integer.parseInt(rt.getName().substring(0, rt.getName().indexOf("@")));

            if (java_pid == pid) {
                System.out.println("In Use\n");
                return true;
            }
        } catch (Exception e) {
            System.out.println("Exception:  " + e.getMessage());
        }
        return false;
    }

Dies habe ich verwendet, als ich eine ähnliche Anforderung hatte.Dadurch wird die PID des Java-Prozesses korrekt ermittelt.Lassen Sie Ihren Java-Code einen Server auf einer vordefinierten Portnummer erzeugen und führen Sie dann Betriebssystembefehle aus, um die PID herauszufinden, die den Port überwacht.Für Linux

netstat -tupln | grep portNumber
Lizenziert unter: CC-BY-SA mit Zuschreibung
Nicht verbunden mit StackOverflow
scroll top