2009-06-25 15 views
2

Ich versuche, Cleartool von einer Java-Anwendung aufrufen, aber Cleartool hängt sogar für eine einfache "-version" -Argument. Das Ausführen von cleardiff anstelle von cleartool funktioniert gut, daher gibt es offensichtlich etwas Spezifisches mit dem cleartool-Programm (von dem ich annehme, dass es mit seinen interaktiven Fähigkeiten zusammenhängt).Fehler beim Starten des Programms von Java (mit ProcessBuilder)

Das folgende Programm

import java.io.*; 
import java.util.*; 

public class ExecTesting extends Thread { 

    private List<String> command = new ArrayList<String>(); 

    public ExecTesting (List<String> command) { 
     super(); 
     this.command = command; 
    } 

    private void print(String s) { 
     System.out.println(s); 
    } 

    @Override 
    public void run() { 
     Process process; 
     OutputStream stdin; 
     InputStream stdout; 
     InputStream stderr; 
     String line; 

     try { 
      String commandString = joinList(command, " "); 
      print("Executing: " + commandString); 

      // runtime.exec has several issues (http://www.javaworld.com/javaworld/jw-12-2000/jw-1229-traps.html?page=1) 
      // better to use ProcessBuilder (http://java.sun.com/developer/JDCTechTips/2005/tt0727.html#2) 
      //process = Runtime.getRuntime().exec(commandString); 
      process = new ProcessBuilder(command).start(); 
      // it fails in both cases though 

      stdin = process.getOutputStream(); 
      stdout = process.getInputStream(); 
      stderr = process.getErrorStream(); 

      BufferedReader bufferedStderr = new BufferedReader(new InputStreamReader(stderr)); 
      while ((line = bufferedStderr.readLine()) != null) { 
       print("stderr: " + line); 
      } 
      bufferedStderr.close(); 

      BufferedReader bufferedStdout = new BufferedReader(new InputStreamReader(stdout)); 
      while ((line = bufferedStdout.readLine()) != null) { 
       print("stdout: " + line); 
      } 
      bufferedStdout.close(); 

      stdin.close(); 
      stdout.close(); 
      stderr.close(); 

      process.waitFor(); 
      print("Execution finished, exit code " + process.exitValue()); 
      process.destroy(); 
     } catch (IOException e) { 
      print("IOException: " +e.getStackTrace()); 
     } catch (InterruptedException e) { 
      print("InterruptedException: " + e.getStackTrace()); 
     } 

    } 

    /* assumes a list with at least one element */ 
    private static String joinList(List<String> list, String glue) { 
     Iterator<String> i = list.iterator(); 
     String ret = i.next(); 
     while (i.hasNext()) { 
      ret += glue + i.next(); 
     } 
     return ret; 
    } 

    public static void main(String[] args) { 
     ArrayList<String> cmd1 = new ArrayList<String>(); 
     cmd1.add("c:\\Program Files\\Rational\\ClearCase\\bin\\cleardiff.exe"); 
     cmd1.add("-version"); 
     ExecTesting et1 = new ExecTesting(cmd1); 
     et1.start(); 

     ArrayList<String> cmd2 = new ArrayList<String>(); 
     //cmd2.add("c:\\Program Files\\Rational\\ClearCase\\bin\\cleardiff.exe"); 
     cmd2.add("c:\\Program Files\\Rational\\ClearCase\\bin\\cleartool.exe"); 
     cmd2.add("-version"); 
     ExecTesting et2 = new ExecTesting(cmd2); 
     et2.start(); 

     et1 = new ExecTesting(cmd1); 
     et1.start(); 
    } 
} 

gibt die folgende Ausgabe

Executing: [c:\Program Files\Rational\ClearCase\bin\cleardiff.exe, -version] 
Executing: [c:\Program Files\Rational\ClearCase\bin\cleartool.exe, -version] 
Executing: [c:\Program Files\Rational\ClearCase\bin\cleardiff.exe, -version] 
stdout: cleardiff       2003.06.10+ (Tue Jul 13 14:02:05 2004) 
Execution finished, exit code 0 

auf die Ausführung des Befehls Cleartool hängen. Wenn stattdessen cmd2 geändert wird, um den Ausgang zu cleardiff wie erwartet

Executing: [c:\Program Files\Rational\ClearCase\bin\cleardiff.exe, -version] 
Executing: [c:\Program Files\Rational\ClearCase\bin\cleardiff.exe, -version] 
Executing: [c:\Program Files\Rational\ClearCase\bin\cleardiff.exe, -version] 
stdout: cleardiff       2003.06.10+ (Tue Jul 13 14:02:05 2004) 
Execution finished, exit code 0 
stdout: cleardiff       2003.06.10+ (Tue Jul 13 14:02:05 2004) 
Execution finished, exit code 0 
stdout: cleardiff       2003.06.10+ (Tue Jul 13 14:02:05 2004) 
Execution finished, exit code 0 

Frage: Weiß jemand, warum Cleartool hängt und wie sie zu beheben?

Antwort

2

Sie sollten die stdout und stderr in separaten Threads konsumieren, sonst wird Blockierungsverhalten auftreten.

Ich vermute, das ist, was in diesem Fall passiert (und dass es nicht verwandt ist mit cleartool/cleardiff anders als sie ausgeben stdout/err). Weitere Informationen finden Sie unter this answer.

3

Es scheint, Sie schließen die I/O-Streams BEFORE Sie beginnen, auf die Beendigung warten. Auch lesen Sie die stderr und stdout sequenziell. Die gelesenen Blöcke sind jedoch stderr, da von der Anwendung keine Fehler gedruckt werden und Sie nicht in die Phase wechseln, in der Sie das stdout gelesen haben. Diese Deadlocks.

Sie könnten die stderr und stdout über ProcessBuilder.redirectErrorStream() beitreten und dann müssen Sie nur stdout lesen.

Ihr Beispiel funktioniert in einigen Fällen, weil die Anwendungsantwort auf dem Stdout nicht die Größe des Kommunikationspuffers trifft, wenn Sie auf dem Stderr blockiert werden. Wenn die Anwendung beendet wird, wird die stderr-Schleife beendet und die Schleife für stdout kann den Inhalt dieses Puffers wiederherstellen.

Verwandte Themen