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.
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.
Antworten:
Es gibt keine plattformunabhängige Methode, die garantiert in allen JVM-Implementierungen funktioniert.
ManagementFactory.getRuntimeMXBean().getName()
sieht aus wie die beste (nächstgelegene) Lösung. Es ist kurz und funktioniert wahrscheinlich in jeder weit verbreiteten Implementierung.
Unter Linux + Windows wird ein Wert wie 12345@hostname
( 12345
als Prozess-ID) zurückgegeben. Beachten Sie jedoch, dass laut Dokument keine Garantie für diesen Wert besteht:
Gibt den Namen der laufenden Java Virtual Machine zurück. Die zurückgegebene Namenszeichenfolge kann eine beliebige Zeichenfolge sein, und eine Java Virtual Machine-Implementierung kann plattformspezifische nützliche Informationen in die zurückgegebene Namenszeichenfolge einbetten. Jede laufende virtuelle Maschine kann einen anderen Namen haben.
In Java 9 kann die neue Prozess-API verwendet werden:
long pid = ProcessHandle.current().pid();
Sie könnten JNA verwenden . Leider gibt es noch keine gemeinsame JNA-API, um die aktuelle Prozess-ID abzurufen, aber jede Plattform ist ziemlich einfach:
Stellen Sie sicher, dass Sie jna-platform.jar
dann haben:
int pid = Kernel32.INSTANCE.GetCurrentProcessId();
Erklären:
private interface CLibrary extends Library {
CLibrary INSTANCE = (CLibrary) Native.loadLibrary("c", CLibrary.class);
int getpid ();
}
Dann:
int pid = CLibrary.INSTANCE.getpid();
Unter Java 9 kann die neue Prozess-API verwendet werden, um die aktuelle Prozess-ID abzurufen. Zuerst greifen Sie zu einem Handle für den aktuellen Prozess und fragen dann die PID ab:
long pid = ProcessHandle.current().pid();
getpid()
Lösung funktioniert auch für OS X mit einem JNA-Aufruf der Bibliothek "System".
error: cannot find symbol
für jdk9
Hier ist eine Backdoor-Methode, die möglicherweise nicht mit allen VMs funktioniert, aber sowohl unter Linux als auch unter Windows funktionieren sollte ( ursprüngliches Beispiel 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);
getDeclaredMethod
für das Objekt aus, das von zurückgegeben wird jvm.get(runtime)
.
Versuchen Sie es mit 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 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;
}
Rufen Sie getProcessId("<PID>")
zum Beispiel einfach an .
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";
}
int pid = Integer.parseInt(new File("/proc/self").getCanonicalFile().getName());
. Warum die zusätzlichen Drehungen?
getCanonicalFile()
Methode, die "Selbst" in die PID umwandelt?
Sie können mein Projekt überprüfen: JavaSysMon auf GitHub. Es bietet eine Prozess-ID und eine Reihe anderer Dinge (CPU-Auslastung, Speichernutzung) plattformübergreifend (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 abzurufen, können Sie die folgende ProcessHandle
Schnittstelle verwenden:
System.out.println(ProcessHandle.current().pid());
In Scala:
import sys.process._
val pid: Long = Seq("sh", "-c", "echo $PPID").!!.trim.toLong
Dies sollte Ihnen eine Problemumgehung auf Unix-Systemen bieten, bis Java 9 veröffentlicht wird. (Ich weiß, die Frage betraf Java, aber da es für Scala keine gleichwertige Frage gibt, wollte ich diese für Scala-Benutzer belassen, die möglicherweise auf dieselbe Frage stoßen.)
Der Vollständigkeit halber gibt es in Spring Boot einen Wrapper für die
String jvmName = ManagementFactory.getRuntimeMXBean().getName();
return jvmName.split("@")[0];
Lösung. Wenn eine Ganzzahl erforderlich ist, kann dies zu einem Einzeiler zusammengefasst werden:
int pid = Integer.parseInt(ManagementFactory.getRuntimeMXBean().getName().split("@")[0]);
Wenn jemand Spring Boot bereits verwendet, verwendet er möglicherweise org.springframework.boot.ApplicationPid
ApplicationPid pid = new ApplicationPid();
pid.toString();
Die toString () -Methode gibt die PID oder '???' aus.
Vorsichtsmaßnahmen bei der Verwendung der ManagementFactory werden bereits in anderen Antworten erläutert.
Das Neueste, was ich gefunden habe, ist, dass es eine Systemeigenschaft namens sun.java.launcher.pid
gibt, die zumindest unter Linux verfügbar ist. Mein Plan ist es, das zu verwenden und wenn es nicht gefunden wird, das zu verwenden JMX bean
.
Es hängt davon ab, wo Sie nach Informationen suchen.
Wenn Sie über die Konsole nach Informationen suchen, können Sie den Befehl jps verwenden. Der Befehl gibt eine Ausgabe ähnlich dem Unix ps-Befehl aus und wird mit dem JDK geliefert, da ich glaube, dass 1.5
Wenn Sie aus dem Prozess schauen, ist die RuntimeMXBean (wie von Wouter Coekaerts gesagt) wahrscheinlich Ihre 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.
Dies ist der Code, den JConsole und möglicherweise von jps und VisualVM verwenden. Es verwendet Klassen aus
sun.jvmstat.monitor.*
Paket, aus 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 nur wenige Fänge:
tool.jar
ist eine Bibliothek, die mit Oracle JDK vertrieben wird, aber nicht mit JRE!tool.jar
von Maven Repo bekommen; Die Konfiguration mit Maven ist etwas schwierigtool.jar
enthält wahrscheinlich plattformabhängigen (nativen?) Code, sodass er nicht einfach zu verteilen istUPDATE: Ich habe gerade überprüft, ob JPS diese Methode verwendet, dh die Jvmstat-Bibliothek (Teil von tool.jar). Es ist also nicht erforderlich, JPS als externen Prozess aufzurufen. Rufen Sie die Jvmstat-Bibliothek direkt auf, wie in meinem Beispiel gezeigt. Auf diese Weise können Sie auch eine Liste aller JVMs abrufen, die auf localhost ausgeführt werden. Siehe JPS- Quellcode :
Ich füge dies anderen Lösungen hinzu.
process id
final RuntimeMXBean runtime = ManagementFactory.getRuntimeMXBean();
final long pid = runtime.getPid();
out.println("Process ID is '" + pid);
Basierend auf Ashwin Jayaprakashs Antwort (+1) über den lizenzierten Apache 2.0 verwende SIGAR
ich Folgendes, um nur die PID des aktuellen Prozesses zu erhalten:
import org.hyperic.sigar.Sigar;
Sigar sigar = new Sigar();
long pid = sigar.getPid();
sigar.close();
Obwohl es nicht auf allen Plattformen funktioniert, funktioniert es unter Linux, Windows, OS X und verschiedenen Unix-Plattformen, wie hier aufgeführt .
Ich weiß, dass dies ein alter Thread ist, aber ich wollte darauf hinweisen, dass die API zum Abrufen der PID (sowie anderer Manipulationen des Java-Prozesses zur Laufzeit) der Process-Klasse in JDK 9 hinzugefügt wird: http: // openjdk. java.net/jeps/102
Ich habe eine Lösung gefunden, die vielleicht ein Randfall ist, und ich habe sie nicht auf einem anderen Betriebssystem als Windows 10 ausprobiert, aber ich denke, es lohnt sich, sie zu bemerken.
Wenn Sie mit J2V8 und nodejs arbeiten, 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();
}
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 ist, was ich verwendet habe, als ich ähnliche Anforderungen hatte. Dies bestimmt die PID des Java-Prozesses korrekt. 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
bash -c 'echo $PPID'
oder die / proc- Antworten oben