Come può un programma Java ottenere il proprio ID di processo?

Come ottengo l’id del mio processo Java?

So che ci sono diversi hack dipendenti dalla piattaforma, ma preferirei una soluzione più generica.

Non esiste alcun modo indipendente dalla piattaforma che possa essere garantito per funzionare in tutte le implementazioni di jvm. ManagementFactory.getRuntimeMXBean().getName() presenta come la soluzione migliore (più vicina). È breve e probabilmente funziona in tutte le implementazioni con largo uso.

Su linux + windows restituisce un valore come [email protected] ( 12345 è l’id di processo). Attenzione però che secondo i documenti , non ci sono garanzie su questo valore:

Restituisce il nome che rappresenta la macchina virtuale Java in esecuzione. La stringa del nome restituita può essere qualsiasi stringa arbitraria e un’implementazione della macchina virtuale Java può scegliere di incorporare informazioni utili specifiche della piattaforma nella stringa del nome restituita. Ogni macchina virtuale in esecuzione potrebbe avere un nome diverso.

In Java 9 è ansible utilizzare la nuova API di processo :

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

Potresti usare JNA . Sfortunatamente non esiste alcuna API JNA comune per ottenere l’ID processo corrente, ma ogni piattaforma è piuttosto semplice:

windows

Assicurati di avere jna-platform.jar quindi:

 int pid = Kernel32.INSTANCE.GetCurrentProcessId(); 

Unix

Dichiarare:

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

Poi:

 int pid = CLibrary.INSTANCE.getpid(); 

Java 9

Sotto Java 9 è ansible utilizzare la nuova API di processo per ottenere l’ID del processo corrente. Per prima cosa devi prendere un handle per il processo corrente, quindi interrogare il PID:

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

Ecco un metodo backdoor che potrebbe non funzionare con tutte le VM ma dovrebbe funzionare sia su Linux che su Windows ( esempio originale qui ):

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

Prova Sigar . API molto estese. Licenza 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(); } 

Il seguente metodo tenta di estrarre il PID da 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 '@', 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; } 

Basta chiamare getProcessId("") , per esempio.

Puoi controllare il mio progetto: JavaSysMon su GitHub. Fornisce l’ID del processo e una serie di altri elementi (utilizzo della CPU, utilizzo della memoria) multipiattaforma (attualmente Windows, Mac OSX, Linux e Solaris)

Per JVM precedenti, in 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"; } 

Da Java 9 esiste un metodo Process.getPid () che restituisce l’ID nativo di un processo:

 public abstract class Process { ... public long getPid(); } 

Per ottenere l’ID di processo dell’attuale processo Java, è ansible utilizzare l’interfaccia ProcessHandle :

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

Per completezza c’è un wrapper in Spring Boot per il

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

soluzione. Se è richiesto un numero intero, questo può essere riassunto in one-liner:

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

Se qualcuno usa già l’avvio Spring, può utilizzare org.springframework.boot.ApplicationPid

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

Il metodo toString () stampa il pid o ‘???’.

Avvertenze che utilizzano ManagementFactory sono già state discusse in altre risposte.

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

L’ultima che ho trovato è che esiste una proprietà di sistema chiamata sun.java.launcher.pid che è disponibile almeno su linux. Il mio piano è di usarlo e se non si trova che usi il JMX bean .

In Scala:

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

Questo dovrebbe darti una soluzione alternativa ai sistemi Unix finché non verrà rilasciato Java 9. (Lo so, la domanda era su Java, ma poiché non c’è una domanda equivalente per Scala, volevo lasciare questo per gli utenti di Scala che potrebbero incappare nella stessa domanda.)

Dipende da dove stai cercando le informazioni.

Se stai cercando le informazioni dalla console puoi usare il comando jps. Il comando fornisce un output simile al comando ps di Unix e viene fornito con JDK poiché credo 1.5

Se stai cercando dal processo il RuntimeMXBean (come detto da Wouter Coekaerts) è probabilmente la scelta migliore. L’output di getName () su Windows utilizzando Sun JDK 1.6 u7 è nel formato [PROCESS_ID] @ [MACHINE_NAME]. Puoi comunque provare a eseguire jps e analizzare il risultato da quello:

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

Se eseguito senza opzioni, l’output dovrebbe essere l’ID del processo seguito dal nome.

Basato sulla risposta di Ashwin Jayaprakash (+1) sul SIGAR licenza Apache 2.0, ecco come lo uso per ottenere solo il PID del processo corrente:

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

Anche se non funziona su tutte le piattaforms, funziona su Linux, Windows, OS X e varie piattaforms Unix come elencato qui .

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

Questo è il codice JConsole e potenzialmente utilizza jps e VisualVM. Utilizza le classi del pacchetto sun.jvmstat.monitor.* , Da 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 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; } } 

Ci sono poche catture:

  • tool.jar è una libreria distribuita con Oracle JDK ma non JRE!
  • Non è ansible ottenere tool.jar dal repository Maven; configurarlo con Maven è un po ‘complicato
  • Probabilmente il tool.jar contiene codice (nativo?) Dipendente dalla piattaforma, quindi non è facilmente distribuibile
  • Funziona partendo dal presupposto che tutte le app JVM (locali) in esecuzione siano “monitorabili”. Sembra che da Java 6 tutte le app in genere siano (a meno che non si configuri triggersmente al contrario)
  • Probabilmente funziona solo per Java 6+
  • Eclipse non pubblica la class principale, quindi non otterrai facilmente il PID di Eclipse. Bug in MonitoredVmUtil?

AGGIORNAMENTO: ho appena verificato che JPS venga usato in questo modo, ovvero la libreria Jvmstat (parte di tool.jar). Quindi non è necessario chiamare JPS come processo esterno, chiamare direttamente la libreria Jvmstat come mostra il mio esempio. Puoi anche ottenere l’elenco di tutte le JVM runnin su localhost in questo modo. Vedi il codice sorgente JPS:

Puoi provare a getpid() in JNR-Posix .

Ha un wrapper Windows POSIX che chiama getpid () su libc.

So che questo è un thread vecchio, ma volevo richiamare quell’API per ottenere il PID (così come altre manipolazioni del processo Java in fase di esecuzione) che viene aggiunto alla class Process in JDK 9: http: // openjdk. java.net/jeps/102

Ecco la mia soluzione:

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

Aggiungendo ad altre soluzioni.

con Java 10, per ottenere l’ process id

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

Ho trovato una soluzione che potrebbe essere un po ‘problematica e non l’ho provata su altri SO di Windows 10, ma penso che ne valga la pena.

Se ti trovi a lavorare con J2V8 e nodejs, puoi eseguire una semplice funzione javascript restituendoti il ​​pid del processo java.

Ecco un esempio:

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

Questo è quello che ho usato quando avevo requisiti simili. Questo determina il PID del processo Java correttamente. Lascia che il tuo codice Java generi un server su un numero di porta predefinito e poi esegui i comandi del SO per scoprire il PID in ascolto sulla porta. Per Linux

 netstat -tupln | grep portNumber