2011-03-12 14 views
21

Se ho un oggetto di processo in Java attraverso Runtime.getRuntime().exec(...), o ProcessBuilder.start(), vedo l'ora attraverso Process.waitFor(), che è come Thread.join(), o potrei uccidere con Process.destroy(), che è come il deprecato Thread.stop().Come posso trovare l'ID di processo (pid) di un processo avviato in java?

MA: Come trovo il pid dell'oggetto Processo? Non vedo un metodo per farlo in The Official Documentation. Posso farlo in Java? Se é cosi, come?

risposta

10

Questo tizio chiama a chiamare per ottenere il PID. Non sono sicuro se esiste una soluzione java al problema.

/** 
* Gets a string representing the pid of this program - Java VM 
*/ 
public static String getPid() throws IOException,InterruptedException { 

    Vector<String> commands=new Vector<String>(); 
    commands.add("/bin/bash"); 
    commands.add("-c"); 
    commands.add("echo $PPID"); 
    ProcessBuilder pb=new ProcessBuilder(commands); 

    Process pr=pb.start(); 
    pr.waitFor(); 
    if (pr.exitValue()==0) { 
    BufferedReader outReader=new BufferedReader(new InputStreamReader(pr.getInputStream())); 
    return outReader.readLine().trim(); 
    } else { 
    System.out.println("Error while getting PID"); 
    return ""; 
    } 
} 

Fonte: http://www.coderanch.com/t/109334/Linux-UNIX/UNIX-process-ID-java-program

+0

Penso che questo darà il pid del processo JVM ... non il processo generato da Java che credo sia quello che la domanda si pone. – splashout

+0

Penso che tu abbia bisogno di leggere un po 'più vicino. Genera un processo in cui solo il lavoro deve far risuonare il proprio PID sul proprio stdout, che a sua volta sta collegando il descrittore del file stdin associato alla JVM. – nsfyn55

+0

I vettori sono vecchi e sincronizzati - non è necessario utilizzare quel tipo di raccolta - prova invece a utilizzare un ArrayList. Sto solo dicendo – user924272

-2

Credo che in Java il vostro colpo migliore è quello di ottenere il tasklist prima e dopo la deposizione delle uova il vostro processo figlio. Crea un diff e ottieni il tuo PID.

è possibile ottenere il Tasklist emettendo un Runtime.getRuntime.exec("tasklist");
noti che Tasklist.exe non è incluso con Windows XP Home edition, ma ancora è possibile scaricarlo.

+0

Si presume che io sia su Windows, cosa che non lo sono. –

7

Simile agli altri strumenti citati, vi è lo strumento da riga di comando jps fornito con il runtime Java. Sputa i PID di tutte le JVM in esecuzione. Il vantaggio è che l'output che si deve analizzare è limitato solo ai processi JVM.

+0

Un altro vantaggio: è multipiattaforma, a differenza della tasklist. –

0

Leo, dopo aver esaminato questo problema per circa una settimana, penso che l'approccio di Jhurtado sia probabilmente l'approccio "migliore" che possiamo gestire in Java al momento. il termine "migliore" è tra virgolette perché ha il pessimo effetto collaterale di essere fondamentalmente una "supposizione" su quale sia il tuo PID figlio.

Se l'app Java sta generando rapidamente processi nativi in ​​un sistema con carichi elevati, NON c'è garanzia che il PID prelevato nel calcolo di diff sia il PID del processo avviato dal thread corrente o che il PID del il processo che hai scelto è stato generato dalla nostra app (forse il sistema host stava già eseguendo comunque quel processo).

Detto questo, se non si generano dozzine di processi o il processo nativo che si sta generando è davvero unico (alcuni programmi personalizzati vengono forniti con l'app), questo approccio funziona correttamente, nel qual caso il PID del processo nativo stai cercando è quello che vuoi.

Su Windows si può usare 'tasklist' come Jhurtado sottolineato per ottenere l'elenco completo dei PID e filtrare per quello che si desidera (utilizzando l'interruttore del filtro/FI non ha funzionato per me in fase di test).

Su qualsiasi sistema * nix è possibile utilizzare "ps ax | grep" dove NOME è un nome di processo come "nginx" o "httpd" che si desidera filtrare per ottenere l'elenco.

Inoltre, se avete bisogno di uccidere i processi randagi (ad esempio, all'uscita VM) su * nix è possibile l'uso di corso "kill -9" e su Windows, abbastanza interessante, è possibile utilizzare 'taskkill '.

Purtroppo non ottimale.

0

Ho avuto lo stesso problema di te.Ho trovato una soluzione abbastanza decente, raccomando un leggero sonno prima che pensasse di assicurare che il processo sia ufficialmente avviato.

Process p = Runtime.getRuntime().exec("cmd /c tasklist"); 
StringWriter writer = new StringWriter(); 
IOUtils.copy(p.getInputStream(), writer); 
String theString = writer.toString(); 
//System.out.println(theString); 
id = findLastString("javaw.exe      .{1,} Console     1", theString); 
System.out.println(id); 

dove findLastString è definito come

public static String findLastString(String pattern, String in) { 
    Pattern p = Pattern.compile(pattern); 
    Matcher matcher = p.matcher(in); 
    String it= ""; 
    while(matcher.find()) { 
     it = matcher.group(); 
     try { 
     Thread.sleep(10); 
     } catch (InterruptedException e) { 
     // TODO Auto-generated catch block 
     e.printStackTrace(); 
     } 
    } 
    int firstIndex=pattern.indexOf(".{1,}"); 
    int lastIndex=it.substring(firstIndex).indexOf(pattern.substring(pattern.indexOf(".{1,}")+5))+firstIndex; 
    String dotOn = it.substring(pattern.indexOf(".{1,}")); 

    it=it.substring(firstIndex, lastIndex); 
    return it; 
} 

Fondamentalmente questo otterrà la lista dei processi in esecuzione, e trovare il più recente correva uno con, in questo caso, il nome javaw.exe (Il mio programma stava iniziando un processo java separato). È possibile sostituire javaw.exe con il nome del processo, che è possibile trovare utilizzando Task Manager. Dovrai anche ottenere il vaso di I/O comune di Apache.

Problemi correlati