Wie erhalte ich die PID des Prozesses, den ich gerade im Java-Programm gestartet habe?
Lesezeit: 7 Minuten
Raf
Ich habe einen Prozess mit folgendem Code gestartet
ProcessBuilder pb = new ProcessBuilder("cmd", "/c", "path");
try {
Process p = pb.start();
}
catch (IOException ex) {}
Jetzt muss ich die PID des Prozesses kennen, den ich gerade gestartet habe.
Dies kann einigen helfen: stackoverflow.com/questions/35842/process-id-in-java
– Grammin
20. Januar 11 um 17:33 Uhr
Keine Ahnung, wie man es in Java macht, aber falls es Ihr Skript ist, können Sie es ändern, damit es seine PID ausgibt und es von p.getInputStream() analysiert.
– maaartinus
20. Januar 11 um 17:37 Uhr
KEIN “exaktes Duplikat” desjenigen, der für das Schließen gestimmt hat. Diese Frage hat damit zu tun, die PID des Java-Prozesses selbst zu finden, nicht einen neuen Prozess, den der Java-Prozess hervorgebracht hat.
– Markus Peters
20. Januar 11 um 17:37 Uhr
Dies gibt die PID der zurück Laufen Host-VM lautete die ursprüngliche Frage, wie die PID des untergeordneten Prozesses lauten würde, der von der laufenden Java-App gestartet wird. Diese Frage adressiert es: stackoverflow.com/questions/5284139/…
Die Process-Klasse ist abstrakt, und was Sie zurückerhalten, ist eine Unterklasse von Process, die für Ihr Betriebssystem entwickelt wurde. Zum Beispiel auf Macs kehrt es zurück java.lang.UnixProcess die ein privates Feld namens hat pid. Mit Reflection können Sie den Wert dieses Felds leicht abrufen. Dies ist zugegebenermaßen ein Hack, aber es könnte helfen. Was braucht man den PID denn überhaupt?
Unter Windows gibt es java.lang.ProcessImpl zurück, das keine Vorstellung von PID hat. Ihre Lösung ist leider nicht plattformübergreifend.
Gibt eine Instanz von „java.lang.Win32Process“) ODER „java.lang.ProcessImpl“ zurück
Beide haben ein privates Feld “Handle”.
Dies ist ein Betriebssystem-Handle für den Prozess. Sie müssen diese + Win32-API verwenden, um PID abzufragen. Auf dieser Seite finden Sie Einzelheiten dazu.
Siehe Antwort von arcsin, wie man es mit JNA macht.
– Panayotis
8. August 17 um 9:53 Uhr
Siehe Antworten von LRBH10 und czerny. Das sind bessere Ansätze im Jahr 2019.
– Shamit Verma
14. Mai 19 um 14:55 Uhr
LRBH10
Im Unix-System (Linux & Mac)
public static synchronized long getPidOfProcess(Process p) {
long pid = -1;
try {
if (p.getClass().getName().equals("java.lang.UNIXProcess")) {
Field f = p.getClass().getDeclaredField("pid");
f.setAccessible(true);
pid = f.getLong(p);
f.setAccessible(false);
}
} catch (Exception e) {
pid = -1;
}
return pid;
}
arcsin
Enthalten jna (sowohl “JNA” als auch “JNA Platform”) in Ihrer Bibliothek und verwenden Sie diese Funktion:
import com.sun.jna.Pointer;
import com.sun.jna.platform.win32.Kernel32;
import com.sun.jna.platform.win32.WinNT;
import java.lang.reflect.Field;
public static long getProcessID(Process p)
{
long result = -1;
try
{
//for windows
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 handl = f.getLong(p);
Kernel32 kernel = Kernel32.INSTANCE;
WinNT.HANDLE hand = new WinNT.HANDLE();
hand.setPointer(Pointer.createConstant(handl));
result = kernel.GetProcessId(hand);
f.setAccessible(false);
}
//for unix based operating systems
else if (p.getClass().getName().equals("java.lang.UNIXProcess"))
{
Field f = p.getClass().getDeclaredField("pid");
f.setAccessible(true);
result = f.getLong(p);
f.setAccessible(false);
}
}
catch(Exception ex)
{
result = -1;
}
return result;
}
Sie können JNA auch von herunterladen Hier und JNA-Plattform von Hier.
Könnten Sie bitte erklären, was der obige Code tut? Auf diese Weise werden alle zukünftigen Besucher verstehen. Danke
– Zeichnete Szurko
15. April 17 um 15:10 Uhr
Die Antwort von Shamit Verma stellt fest, warum es so gemacht werden muss. Windows gibt Ihnen keine PID, sondern ein Handle, also müssen Sie das Handle in PID umwandeln.
– Panayotis
8. August 17 um 9:54 Uhr
Glenneroo
Ich glaube, ich habe eine Lösung gefunden, die ziemlich kugelsicher aussieht, während sie auf den meisten Plattformen funktioniert. Hier ist die Idee:
Erstellen Sie einen JVM-weiten Mutex, den Sie erwerben, bevor Sie einen neuen Prozess erzeugen/einen Prozess beenden
Verwenden Sie plattformabhängigen Code, um die Liste der untergeordneten Prozesse + PIDs Ihres JVM-Prozesses abzurufen
Spawnen Sie einen neuen Prozess
Erwerben Sie eine neue Liste von untergeordneten Prozessen + PIDs und vergleichen Sie sie mit der vorherigen Liste. Der Neue ist dein Typ.
Da Sie nur nach untergeordneten Prozessen suchen, kann Ihnen kein anderer Prozess auf derselben Maschine Unrecht tun. JVM-weiter Mutex gibt Ihnen dann die Gewissheit, dass der neue Prozess der richtige ist.
Das Lesen der untergeordneten Prozessliste ist einfacher als das Abrufen der PID von Prozessobjekten, da es keine WIN-API-Aufrufe unter Windows erfordert und, was noch wichtiger ist, es wurde bereits in mehreren Bibliotheken durchgeführt.
Unten ist eine Implementierung der obigen Idee mit JavaSysMon Bücherei. Es
class UDKSpawner {
private int uccPid;
private Logger uccLog;
/**
* Mutex that forces only one child process to be spawned at a time.
*
*/
private static final Object spawnProcessMutex = new Object();
/**
* Spawns a new UDK process and sets {@link #uccPid} to it's PID. To work correctly,
* the code relies on the fact that no other method in this JVM runs UDK processes and
* that no method kills a process unless it acquires lock on spawnProcessMutex.
* @param procBuilder
* @return
*/
private Process spawnUDK(ProcessBuilder procBuilder) throws IOException {
synchronized (spawnProcessMutex){
JavaSysMon monitor = new JavaSysMon();
DirectUDKChildProcessVisitor beforeVisitor = new DirectUDKChildProcessVisitor();
monitor.visitProcessTree(monitor.currentPid(), beforeVisitor);
Set<Integer> alreadySpawnedProcesses = beforeVisitor.getUdkPids();
Process proc = procBuilder.start();
DirectUDKChildProcessVisitor afterVisitor = new DirectUDKChildProcessVisitor();
monitor.visitProcessTree(monitor.currentPid(), afterVisitor);
Set<Integer> newProcesses = afterVisitor.getUdkPids();
newProcesses.removeAll(alreadySpawnedProcesses);
if(newProcesses.isEmpty()){
uccLog.severe("There is no new UKD PID.");
}
else if(newProcesses.size() > 1){
uccLog.severe("Multiple new candidate UDK PIDs");
} else {
uccPid = newProcesses.iterator().next();
}
return proc;
}
}
private void killUDKByPID(){
if(uccPid < 0){
uccLog.severe("Cannot kill UCC by PID. PID not set.");
return;
}
synchronized(spawnProcessMutex){
JavaSysMon monitor = new JavaSysMon();
monitor.killProcessTree(uccPid, false);
}
}
private static class DirectUDKChildProcessVisitor implements ProcessVisitor {
Set<Integer> udkPids = new HashSet<Integer>();
@Override
public boolean visit(OsProcess op, int i) {
if(op.processInfo().getName().equals("UDK.exe")){
udkPids.add(op.processInfo().getPid());
}
return false;
}
public Set<Integer> getUdkPids() {
return udkPids;
}
}
}
Könnten Sie bitte erklären, was der obige Code tut? Auf diese Weise werden alle zukünftigen Besucher verstehen. Danke
– Zeichnete Szurko
15. April 17 um 15:10 Uhr
Die Antwort von Shamit Verma stellt fest, warum es so gemacht werden muss. Windows gibt Ihnen keine PID, sondern ein Handle, also müssen Sie das Handle in PID umwandeln.
– Panayotis
8. August 17 um 9:54 Uhr
In meinen Tests hatten alle IMPL-Klassen das Feld “PID”. Das hat bei mir funktioniert:
public static int getPid(Process process) {
try {
Class<?> cProcessImpl = process.getClass();
Field fPid = cProcessImpl.getDeclaredField("pid");
if (!fPid.isAccessible()) {
fPid.setAccessible(true);
}
return fPid.getInt(process);
} catch (Exception e) {
return -1;
}
}
Stellen Sie nur sicher, dass der zurückgegebene Wert nicht -1 ist. Wenn dies der Fall ist, analysieren Sie die Ausgabe von ps.
Es gilt nicht java.lang.ProcessImpl. Bei mir schlägt es zum Beispiel unter Windows fehl.
– Oliver Gondža
8. Februar 16 um 9:50 Uhr
.
7575800cookie-checkWie erhalte ich die PID des Prozesses, den ich gerade im Java-Programm gestartet habe?yes
Dies kann einigen helfen: stackoverflow.com/questions/35842/process-id-in-java
– Grammin
20. Januar 11 um 17:33 Uhr
Keine Ahnung, wie man es in Java macht, aber falls es Ihr Skript ist, können Sie es ändern, damit es seine PID ausgibt und es von p.getInputStream() analysiert.
– maaartinus
20. Januar 11 um 17:37 Uhr
KEIN “exaktes Duplikat” desjenigen, der für das Schließen gestimmt hat. Diese Frage hat damit zu tun, die PID des Java-Prozesses selbst zu finden, nicht einen neuen Prozess, den der Java-Prozess hervorgebracht hat.
– Markus Peters
20. Januar 11 um 17:37 Uhr
Dies gibt die PID der zurück Laufen Host-VM lautete die ursprüngliche Frage, wie die PID des untergeordneten Prozesses lauten würde, der von der laufenden Java-App gestartet wird. Diese Frage adressiert es: stackoverflow.com/questions/5284139/…
– Riad Kalla
16. August 11 um 1:42 Uhr
Es ist möglich, dass Java 9 eine Standard-API dafür bereitstellt: openjdk.java.net/jeps/102
– Raedwald
13. Mai ’15 um 9:31 Uhr