2011-03-12 43 views
21

Si consigo un objeto de proceso en Java a través Runtime.getRuntime().exec(...) o ProcessBuilder.start(), puedo esperar para ello a través Process.waitFor(), que es como Thread.join(), o podría matar con Process.destroy(), que es como el Thread.stop() obsoleta.¿Cómo puedo encontrar el ID de proceso (pid) de un proceso iniciado en Java?

PERO: ¿Cómo puedo encontrar el pid del objeto de proceso? No veo un método para hacerlo en The Official Documentation. ¿Puedo hacer esto en Java? ¿Si es así, cómo?

Respuesta

10

Este tipo llama a bash para obtener el PID. No estoy seguro de si hay una solución Java para el 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 ""; 
    } 
} 

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

+0

Creo que esto dará el pid del proceso de JVM ... no el proceso creado por Java, que creo que es lo que la pregunta está haciendo. – splashout

+0

Creo que necesitas leer un poco más. Genera un proceso que solo requiere hacer eco de su propio PID en su stdout, que a su vez está conectado al descriptor de archivo stdin asociado con la JVM. – nsfyn55

+0

Los vectores son anticuados, y están sincronizados, no es necesario utilizar ese tipo de colección; intente utilizar una ArrayList. Solo digo. – user924272

-2

pienso en Java es su mejor tiro para obtener el tasklist antes y después del desove el proceso hijo. Haz una diferencia y obtén tu PID.

se puede obtener la lista de tareas mediante la emisión de un aviso Runtime.getRuntime.exec("tasklist");
que Tasklist.exe no está incluido con Windows XP Home Edition, pero todavía puede descargarlo.

+0

Estás asumiendo que estoy en Windows, que no soy. –

7

Similar a las otras herramientas mencionadas, existe la herramienta de línea de comandos jps que viene con el tiempo de ejecución de Java. Escupe los PID de todas las JVM en ejecución. El beneficio es que la salida que se debe analizar se limita solo a los procesos de JVM.

+0

Otro beneficio: es multiplataforma, a diferencia de la lista de tareas. –

0

Leo, después de analizar este tema durante aproximadamente una semana, creo que el enfoque de Jhurtado es probablemente el "mejor" enfoque que podemos administrar en Java en este momento. "mejor" es entre comillas porque tiene el muy desagradable efecto secundario de ser básicamente una "adivinanza" de lo que es el PID de su hijo.

Si su aplicación Java está generando procesos nativos rápidamente en un sistema de alta carga, NO hay garantía de que el PID que recoja en su cálculo de diferencia sea el PID del Proceso iniciado por el Subproceso actual o que el PID del El proceso que elegiste fue generado por nuestra aplicación (tal vez el sistema host ya estaba ejecutando ese proceso de todos modos).

Dicho esto, si no está generando docenas de procesos o el proceso nativo que está generando es realmente único (algunos servicios personalizados que envía con su aplicación) entonces este enfoque funciona bien, en cuyo caso el PID del proceso nativo lo que estás buscando es el que quieres.

En Windows puede usar 'tasklist' como señaló Jhurtado para obtener la lista completa de PIDs y filtrar para la que desea (utilizando el interruptor de filtro/FI no funcionó para mí en las pruebas).

En cualquier sistema * nix puede usar "ps ax | grep" donde NAME es un nombre de proceso como 'nginx' o 'httpd' que desea filtrar para obtener su lista.

Además, si usted necesita para matar procesos callejeros (por ejemplo, en la salida VM) en * nix se puede, por supuesto uso "kill -9" y en Windows, curiosamente, puede utilizar 'taskkill '.

Desafortunadamente desafortunadamente.

0

Me encontré con el mismo problema que usted.Encontré una solución bastante decente, recomiendo dormir un poco antes de pensar para garantizar que el proceso se haya iniciado oficialmente.

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

donde findLastString se define como

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

Básicamente esto hará que la lista de procesos en ejecución, y encontrar el más recientemente corrió con uno, en este caso, el nombre javaw.exe (Mi programa estaba comenzando un proceso separado de java). Puede reemplazar javaw.exe con el nombre del proceso, que puede encontrar utilizando el Administrador de tareas. También necesitarás obtener el jar común de IO de Apache.

Cuestiones relacionadas