2009-06-25 7 views
2

javaアプリケーションからcleartoolを呼び出そうとしていますが、単純な "-version"引数でもcleartoolがハングします。 cleartoolの代わりにcleardiffを動かすとうまくいくので、明らかにcleartoolプログラムに特有のことがあります(対話的な機能に関連していると思います)。javaからProcessBuilderを使用してプログラムを起動できません

次のプログラム

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

はのcleartoolコマンドの実行に掛かって次の出力

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 

を与えます。代わりにCMD2は、出力をcleardiffように変更された場合、期待どおりである

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 

が質問:のcleartoolがぶら下がって、どのように修正することですなぜ誰もが知っていますか?

答えて

2

別のスレッドでstdoutとstderrを使用する必要があります。そうしないと、ブロック動作が発生します。

私は、このインスタンスで何が起きているのだろうと思っています(そして、stdout/errを出力している以外はcleartool/cleardiffとは関係ありません)。詳細については、this answerを参照してください。

3

I/Oストリームを閉じると思われます。BEFORE終了を待つことを開始します。また、stderrとstdoutを順番に読み取ります。ただし、アプリケーションからエラーが出力されず、stdoutを読み込んだフェーズに移動しないため、stderrへの読み取りはブロックされます。このデッドロック。

stderrとstdoutにはProcessBuilder.redirectErrorStream()で参加することができます。その後、stdoutを読むだけで済みます。

stderrでブロックされていると、stdoutのアプリケーション応答が通信バッファのサイズに達しないため、サンプルが動作することがあります。アプリケーションが終了すると、stderrループが終了し、stdoutのループはそのバッファの内容をretieveすることができます。

関連する問題