2011-09-19 12 views
6

Sto usando ProcessBuilder di Java per avviare un sottoprocesso, che è un altro programma Java che deve funzionare in un JVM separata.sottoprocesso avviato da Java utilizzando finiture waitFor ma i flussi non vengono terminati

comincio due fili di leggere i stdout e stderr flussi dal processo, in modo che non ci sia appendere se i buffer di flusso sono pieni. La chiamata a Process.waitFor restituisce ma gli stream non vengono terminati.

Il codice che sto usando sembra qualcosa di simile (comando è una lista di stringhe):

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

Se corro qualcosa di diverso, come ad esempio "java -version" o "dir" o qualcosa del genere, il codice funziona bene. ho accesso al codice Java che sto cercando di correre, ma non ho mai sentito dire che si dovrebbe chiamare close() su System.out.

+0

Potreste essere interessati a mia domanda circa la chiusura del processo flussi appropriata: http://stackoverflow.com/questions/7065067/how-to-close-std -streams-da-java-lang-processo-appropriata Un altro link utile: http://mark.koli.ch/2011/01/leaky-pipes-remember-to-close-your-streams-when-using- javas-runtimegetruntimeexec.html –

+0

Se uso 'IOUtils.closeQuietly' o anche chiamo' close() 'sui flussi prima delle chiamate' join() ', il programma si blocca invece su quella chiamata. –

+0

Questo è molto probabilmente perché 'IOUtils.copy (in, out)' 'usa InputStream.read (byte [])' e che blocca e in attesa di dati in arrivo. Pertanto i thread sono in esecuzione per sempre e quindi 'join() 'attende per sempre. Devi forzare la chiusura qui dopo un determinato timeout. Per favore prova un'implementazione come quella che ho postato nella mia risposta dal link che ti ho dato. Scommetto che può gestirlo qui. –

risposta

0

Come so da this website è necessario chiudere tutti i STD-stream da oggetto di processo da soli. Indipendentemente se usato prima o no. Questo sembra altamente correlato al garbage collector G1 (predefinito dal momento che Java 7 afaik) mantiene le pipe aperte quando non vengono chiuse esplicitamente, anche quando il sottoprocesso termina.

Non ho familiarità con gli interni qui ma il codice che ho postato in my answer alla mia domanda funziona bene su un sistema 24/7 che chiama GhostScript e altri molto.

Altre domande e risposte su SO affermando che è necessario chiudere STD-flussi di processo esplicito:

Problemi correlati