In pseudocodice, ecco quello che sto facendo:Process.waitFor(), filati, e InputStreams
Process proc = runtime.exec(command);
processOutputStreamInThread(proc.getInputStream());
processOutputStreamInThread(proc.getErrorStream());
proc.waitFor()
Tuttavia, a volte processOutputStreamInThread
non vede alcun output e, a volte lo fa. Approssimativamente, il metodo crea un BufferedInputStream
dell'output del comando e lo invia a un logger.
In base a quello che vedo, sto cercando di indovinare che command
non deve avere tutto il suo output scaricati in corsi d'acqua alimentati da getInputStream()
e getErrorStream()
, permettendo in tal modo il flusso di essere vuota.
I risultati delle mie prove sono le seguenti domande:
(1) Vuol waitFor()
nel java.lang.Process richiedono l'output del programma eseguito a sono stati letti prima che ritorni?
La documentazione indica solo:
provoca il thread corrente di aspettare, se necessario, fino a quando il processo rappresentata dall'oggetto
Process
è terminato. Questo metodo restituisce immediatamente se il sottoprocesso è già terminato. Se il sottoprocesso non è ancora terminato, il thread chiamante verrà bloccato fino alla chiusura del sottoprocesso.
(2) A quali condizioni fanno i flussi forniti da getInputStream
e getErrorStream
devono essere chiusi e/o sono chiuse automaticamente?
La documentazione afferma soltanto:
ottiene il flusso di errore del sottoprocesso. Lo stream ottiene i dati inviati tramite pipe dal flusso di output di errore del processo rappresentato da questo oggetto Process.
Nota di implementazione: È consigliabile memorizzare il buffer di input.
Uno user reports che ha dovuto chiudere il se stesso flussi, ma ottengo un'eccezione, almeno una parte del tempo che indica che il flusso è già chiusa quando tento di farlo.
Modifica: modificato getOutputStream
a getInputStream
, ora presente sopra.
Risoluzione: Il problema ha finito per essere che in alcuni casi i fili utilizzati per elaborare il flusso di output non sarebbe correre fino a dopo il mio processo molto breve aveva completato, con conseguente flusso di input avermi dato nessun dato. waitFor
non ha atteso l'output del programma eseguito. Piuttosto, il programma è stato eseguito e terminato prima che qualsiasi output potesse essere raccolto.
Ho usato thread perché non sono sicuro di quanto output avrei dovuto ottenere su errore standard e output standard e volevo essere in grado di elaborare entrambi contemporaneamente, senza bloccare uno o l'altro se solo uno di essi avesse dati disponibili. Ma, poiché i miei thread non possono leggere in modo coerente l'output del programma eseguito, è una non soluzione.
miei Coded finali sembravano qualcosa di simile:
ProcessBuilder pb = new ProcessBuilder(cmdargs);
pb.redirectErrorStream(true);
Process proc = pb.start();
processOutputStream(proc.getInputStream());
proc.waitFor()
Anche gli altri flussi devono essere chiusi se vengono utilizzati? Sono implicitamente chiusi quando il processo termina? –
@Kaleb Ho aggiunto una risposta alla tua domanda al mio post. –
Per quanto riguarda l'articolo JavaWorld, c'è un bug con la soluzione finale. Se un processo si interrompe molto rapidamente, errorGobbler e outputGobbler potrebbero non aver ancora eseguito e consumato i dati. Il codice dovrebbe essere: proc.waitFor(); errorGobbler.join(); outputGobbler.join() ;. Ciò ha costretto il thread principale ad attendere fino a quando i flussi non hanno finito di leggere l'input. –