2011-09-19 9 views
6

Estoy usando Java ProcessBuilder para iniciar un subproceso, que es otro programa Java que debe ejecutarse en una JVM por separado.El subproceso iniciado desde Java termina usando waitFor pero las secuencias no finalizan

Comienzo dos subprocesos para leer de las corrientes stdout y stderr del proceso, de modo que no haya bloqueo si los almacenamientos intermedios de la secuencia están llenos. La llamada a Process.waitFor regresa pero las transmisiones no finalizan.

El código que estoy usando algo como miradas (comando es una lista de cadenas):

ProcessBuilder pb = new ProcessBuilder(command); 

final Process p = pb.start(); 
final ByteArrayOutputStream outStream = new ByteArrayOutputStream(); 
final ByteArrayOutputStream errStream = new ByteArrayOutputStream(); 

Thread outputThread = new Thread() { 
    @Override 
    public void run() { 
     try { 
      IOUtils.copy(p.getInputStream(), outStream); 
     } catch (IOException e) { 
      e.printStackTrace(); 
     } 
    }; 
}; 
outputThread.start(); 

Thread errorThread = new Thread() { 
    @Override 
    public void run() { 
     try { 
      IOUtils.copy(p.getErrorStream(), errStream); 
     } catch (IOException e) { 
      e.printStackTrace(); 
     } 
    }; 
}; 
errorThread.start(); 

int returncode = p.waitFor(); 
outputThread.join(); 
errorThread.join(); 

Si me quedo otra cosa, como por ejemplo "java -version" o "dir" o algo así, el código funciona bien. Tengo acceso al código de Java que estoy tratando de ejecutar, pero nunca escuché que debería llamar a close() en System.out.

+0

Usted puede estar interesado en mi pregunta sobre el cierre del proceso corrientes apropiado: http://stackoverflow.com/questions/7065067/how-to-close-std -streams-from-java-lang-process-appropriate Otro enlace útil: http://mark.koli.ch/2011/01/leaky-pipes-remember-to-close-your-streams-when-using- javas-runtimegetruntimeexec.html –

+0

Si utilizo 'IOUtils.closeQuietly' o incluso llamo' close() 'en las transmisiones antes de las llamadas' join() ', el programa se cuelga en esa llamada. –

+0

Esto es muy probable porque 'IOUtils.copy (in, out)' usa 'InputStream.read (byte [])' y está bloqueando y esperando datos entrantes. Por lo tanto, los hilos se ejecutan para siempre y, por lo tanto, 'join()' espera para siempre. Debe forzar el cierre aquí después de que excede un tiempo de espera determinado. Pruebe una implementación como la que publiqué en mi respuesta del enlace que le di. Apuesto a que puede manejar esto aquí. –

Respuesta

0

Como sé por this website debe cerrar todos los std-streams del objeto Process por su cuenta. Independientemente si se usa antes o no. Esto parece muy relacionado con el recolector de basura G1 (predeterminado desde Java 7 afaik) que mantiene las tuberías abiertas cuando no se cierran explícitamente, incluso cuando el subproceso finaliza.

No estoy familiarizado con las partes internas aquí, pero el código que publiqué en my answer a mi pregunta funciona bien en un sistema 24/7 que llama mucho a GhostScript y otros.

Otras preguntas y respuestas sobre SO indicando que debe cerrar Proceso STD-corrientes explícita:

Cuestiones relacionadas