Come trovo il mio PID in Java o JRuby su Linux?
Domanda
Devo trovare il PID dell'attuale processo in esecuzione su una piattaforma Linux (può essere una soluzione dipendente dal sistema). Java non supporta il recupero dell'ID processo e JRuby attualmente ha un bug con il metodo Ruby, Process.pid.
Esiste un altro modo per ottenere il PID?
Soluzione
Se hai procfs , puoi trovare l'id del processo tramite / proc / self symlink, che punta a una directory il cui nome è il pid (qui ci sono anche file con altre informazioni pertinenti, incluso il PID, ma la directory è tutto ciò che serve in questo caso).
Quindi, con Java, puoi fare:
String pid = new File("/proc/self").getCanonicalFile().getName();
In JRuby, puoi utilizzare la stessa soluzione:
pid = java.io.File.new("/proc/self").canonical_file.name
Un ringraziamento speciale al canale #stackoverflow sul nodo libero per avermi aiutato a risolvere questo problema! (in particolare, Jerub , gregh e Topdeck )
Altri suggerimenti
Testato solo su Linux usando Sun JVM. Potrebbe non funzionare con altre implementazioni JMX.
String pid = ManagementFactory.getRuntimeMXBean().getName().split("@")[0];
È possibile utilizzare l'interfaccia JNI per chiamare la funzione POSIX getpid (). È abbastanza semplice. Si inizia con una classe per le funzioni POSIX necessarie. Lo chiamo POSIX.java
:
import java.util.*;
class POSIX
{
static { System.loadLibrary ("POSIX"); }
native static int getpid ();
}
Compilalo con
$ javac POSIX.java
Successivamente si genera un file di intestazione POSIX.h
con
$ javah -jni POSIX
Il file di intestazione contiene il prototipo C per la funzione che racchiude la funzione getpid. Ora devi implementare la funzione, che è abbastanza facile. L'ho fatto in POSIX.c
:
#include "POSIX.h"
#include <sys/types.h>
#include <unistd.h>
JNIEXPORT jint JNICALL Java_POSIX_getpid (JNIEnv *env, jclass cls)
{
return getpid ();
}
Ora puoi compilarlo usando gcc:
$ gcc -Wall -I/usr/lib/jvm/java-1.6.0-sun-1.6.0.21/include -I/usr/lib/jvm/java-1.6.0-sun-1.6.0.21/include/linux -o libPOSIX.so -shared -Wl,-soname,libPOSIX.so POSIX.c -static -lc
Devi specificare la posizione in cui è installato Java. È tutto. Ora puoi usarlo. Crea un semplice programma getpid:
public class getpid
{
public static void main (String argv[])
{
System.out.println (POSIX.getpid ());
}
}
Compilalo con javac getpid.java
ed eseguilo:
$ java getpid &
[1] 21983
$ 21983
Il primo pid è scritto dalla shell e il secondo è scritto dal programma Java dopo che è stato restituito il prompt della shell. & # 8718;
Genera un processo shell che leggerà il pid del suo genitore. Questo deve essere il nostro pid. Ecco il codice in esecuzione, senza eccezioni e gestione degli errori.
import java.io.*;
import java.util.Scanner;
public class Pid2
{
public static void main(String sArgs[])
throws java.io.IOException, InterruptedException
{
Process p = Runtime.getRuntime().exec(
new String[] { "sh", "-c", "ps h -o ppid $" });
p.waitFor();
Scanner sc = new Scanner(p.getInputStream());
System.out.println("My pid: " + sc.nextInt());
Thread.sleep(5000);
}
}
Questa soluzione sembra essere la migliore se il PID deve essere ottenuto solo per emettere un altro comando shell. È sufficiente racchiudere il comando tra virgolette per passare come argomento a un altro comando, ad esempio:
nice `ps h -o ppid $`
Questo può sostituire l'ultima stringa nella matrice data alla chiamata exec
.
Puoi provare getpid () in JNR-Posix .
Ha anche un wrapper POSIX per Windows che chiama getpid () fuori da libc. Nessun JNI necessario.
Java 9
offre finalmente un modo ufficiale per farlo con ProcessHandle :
ProcessHandle.current().pid();
Questa:
-
Per prima cosa ottiene un riferimento
ProcessHandle
per il processo corrente. -
Per accedere al suo
pid
.
Nessuna importazione necessaria in quanto ProcessHandle
fa parte di java.lang
.