2010-07-27 3 views
3

je l'extrait de code suivant:flux de lecture de java Runtime.exec

Process proc = runtime.exec(command); 
errorGobbler = new ErrorStreamGobbler(proc.getErrorStream(), logErrors, mdcMap); 
outputGobbler = new OutputStreamGobbler(proc.getInputStream(), mdcMap); 
executor.execute(errorGobbler); 
executor.execute(outputGobbler); 
processExitCode = proc.waitFor(); 

où les dindons sont Runnable s qui utilisent un BufferedReader pour lire les flux d'entrée et d'erreur du processus d'exécution. Alors que cela fonctionne la plupart du temps, je reçois la fenêtre occasionnelle (environ 2 minutes) où j'obtiens le processExitCode comme 0, ce qui indique une terminaison normale mais il n'y a rien dans les flux d'entrée et d'erreur - rien n'indique même la fin - de-flux.

Comme je l'ai déjà dit, cela fonctionne la plupart du temps, mais cet échec se produit de temps en temps - et je suis totalement perplexe. Des idées?

Rags

+0

Un peu plus de contexte - il s'agit d'une application multithread où beaucoup de Runtime.exec() se produisent simultanément. Rags – ragstorooks

+0

Vous voulez dire que les gobblers de cours d'eau bloquent pour toujours? – EJP

+0

Oui, ils le font! Ils ont juste accroché ... – ragstorooks

Répondre

11

J'ai eu du mal avec le même genre de questions. Je ne me souviens plus exactement de ce qui n'allait pas (j'ai peut-être oublié de rincer/fermer les flux correctement ou quelque chose ...). En tout cas, voici ce que j'ai trouvé.

/** 
* Handle communication with a process, reading its output/error and feeding its input 
* @param process The process to execute 
* @param _in Reader that will feed the input pipe of the process 
* @param out Writer that will receive the output of the process 
* @param err Writer that will receive the error pipe of the process 
*/ 
public static void communicate(
     Process process, 
     final Reader _in, 
     final Writer out, 
     final Writer err) 
{ 
    // Buffer the input reader 
    final BufferedReader in = new BufferedReader(_in); 

    // Final versions of the the params, to be used within the threads 
    final BufferedReader stdOut = new BufferedReader(new InputStreamReader(process.getInputStream())); 
    final BufferedReader stdErr = new BufferedReader(new InputStreamReader(process.getErrorStream())); 
    final BufferedWriter stdIn = new BufferedWriter(new OutputStreamWriter(process.getOutputStream())); 

    // Thread that reads std out and feeds the writer given in input 
    new Thread() { 
     @Override public void run() { 
      String line; 
      try { 
       while ((line = stdOut.readLine()) != null) { 
        out.write(line + newline); 
       } 
      } catch (Exception e) {throw new Error(e);} 
      try { 
       out.flush(); 
       out.close(); 
      } catch (IOException e) { /* Who cares ?*/ } 
     } 
    }.start(); // Starts now 

    // Thread that reads std err and feeds the writer given in input 
    new Thread() { 
     @Override public void run() { 
      String line; 
      try { 
       while ((line = stdErr.readLine()) != null) { 
        err.write(line + newline); 
       } 
      } catch (Exception e) {throw new Error(e);} 
      try { 
       err.flush(); 
       err.close(); 
      } catch (IOException e) { /* Who cares ?*/ } 
     } 
    }.start(); // Starts now 

    // Thread that reads the std in given in input and that feeds the input of the process 
    new Thread() { 
     @Override public void run() { 
      String line; 
      try { 
       while ((line = in.readLine()) != null) { 
        stdIn.write(line + newline); 
       } 
      } catch (Exception e) {throw new Error(e);} 

      try { 
       stdIn.flush(); 
       stdIn.close(); 
      } catch (IOException e) { /* Who cares ?*/ } 
     } 
    }.start(); // Starts now 

    // Wait until the end of the process 
    try { 
     process.waitFor(); 
    } catch (Exception e) { 
     throw new Error(e); 
    } 

} // End of #communicate 

J'espère que cela aide.

+0

Je faisais déjà tout cela et voyais encore beaucoup de ces problèmes. Après beaucoup d'essais et d'erreurs, je pense que j'ai finalement compris: le pool de threads manquait de threads (même s'il ne devrait pas l'être) et les threads pour lire les streams n'ont jamais réellement démarré. Je vais porter cette question sur les forums de printemps! (J'utilise leur implémentation de pool de threads) Merci pour votre contribution! – ragstorooks