2009-03-14 2 views
6

Il mio programma Java utilizza ProcessBuilder (con il set redirectErrorStream true) e ha un ciclo che esegue il metodo di lettura di inputstream dei processi, che sta bloccando. Il programma esterno che sto chiamando si ferma quindi in attesa di input e stdin. Ora voglio uccidere il processo. Questo non viene fatto da (in un thread separato) chiamando il metodo destroy del processo e chiamando il metodo close di inputstream per impedire il blocco del metodo read, in modo che il thread iniziale possa terminare la sua vita?perché il blocco inputstream.close() di java?

Per alcuni motivi process.getInputStream().close() blocchi. Dal JavaDoc non vedo perché questo possa accadere. Inoltre, non capisco perché javadoc dice "Il metodo close di InputStream non fa nulla". (link to javadoc) Qualcuno potrebbe spiegarlo?

Grazie :-)

+0

Sei sicuro che ciò non accada a causa del programma esterno in esecuzione? – Geo

risposta

4

Per quanto riguarda il comportamento di blocco, esiste un problema noto in Java che può causare un deadlock durante la comunicazione con un altro processo. Non posso dire se questo è ciò che stai vedendo, ma vale la pena esaminarlo. Il documento per la java.lang.Process dice:

Poiché alcune piattaforme native solo forniscono la dimensione del buffer limitata per flussi di input e output standard, mancato di scrivere tempestivamente il flusso di ingresso o leggere il flusso di output del il sottoprocesso può causare il sottoprocesso da bloccare e persino il deadlock .

+0

Lo esaminerò, grazie – Allanrbo

+0

Ho riscontrato lo stesso problema. Esiste un modo per gestire la dimensione del buffer limitata e quindi evitare di bloccare il sottoprocesso? – JorgeGRC

3

Per qualche motivo process.getInputStream(). Chiudi() blocchi. Da JavaDoc non vedo perché questo può accadere. Inoltre, I non capisco perché javadoc dice "Il metodo close di InputStream non ha nulla di ". (link a javadoc) Potrebbe qualcuno spiegare questo?

Se si guarda Javadoc, si vedrà che InputStream è una classe astratta. Le sottoclassi che estendono InputStream dovrebbero sostituire il metodo close() (se necessario). Chiaramente la sottoclasse InputStream che stai usando fa qualcosa nel metodo close.

+0

ovviamente, questo ha senso. Non ho notato che l'inputstream era astratto, grazie. – Allanrbo

3

In aggiunta a ciò che jdigital ha scritto, controllare questo article. Si tratta del metodo Runtime.exec() e ProcessBuilder è stato introdotto in Java 5, ma mi sembra che la discussione possa essere estrapolata ai processi di sistema in generale.

3

Penso di aver capito. Ovviamente è importante chiamare process.getOutputStream(). Close() prima di process.getInputStream(). Close() e process.getErrorStream(). Close().

+0

Perché è importante chiudere il flusso di output prima del flusso di input? – Michael

+0

scusate, intendevo "apparentemente". Non ho mai capito perché ... – Allanrbo

+0

Grazie :) Ti farò una nuova domanda su SO su di esso ... – Michael

-1

Ho avuto lo stesso problema e dopo un bel po 'di difficoltà, ho trovato una soluzione, che consiste nell'usare InputStream#available() prima di leggere qualsiasi cosa dagli stream Process. Un frammento della mia soluzione è disponibile here.

+0

Il ragazzo che ha votato potrebbe forse spiegare il suo punto. –

+0

Non ti ho minimizzato, ma non penso che sia corretto. Chiamando 'available()' ti dice quanti dati Java ha già letto, o ne è a conoscenza. È del tutto possibile che più è stato scritto nei buffer del sistema operativo e Java non ha ancora avuto la possibilità di vederli. Un rapido test ha verificato che 'available()' non cattura l'intera lunghezza di una stringa 'echo'ed molto lunga. – dimo414