0

クラスファイルを一緒にjarするJava cdeがあります:

    List<String> args = new ArrayList<String>();
    String path = FileSystemUtils.JavaBin() + "\\jar.exe";
    args.add(path);
    args.add("-cfv");
    args.add(jarName);
    args.addAll(FileSystemUtils.getAllFiles(directory, ".class"));
    ProcessBuilder pb = new ProcessBuilder(args);
    File wd = new File(directory);
    pb.directory(wd);
    Process p = pb.start();
    //Waiting for process to exit
    p.waitFor();
    int res = p.exitValue();

このコードはうまく機能します。ただし、一部のコンピューターでは、すべてではありませんが、7 つ以上のファイルがある場合p.waitFor();、jar が作成されていても、決して返されません。

タスクマネージャを見てみると、本当にjar.exeが終了していませんでした....何が原因でしょうか?コマンド ラインから同じコマンドを手動で実行すると、すぐに終了します。

これは非常に奇妙に思えます。誰かがヒントを持っていますか?

4

1 に答える 1

0

自分で解決策を見つけました。どうやらProcessBuilder.startJavaで外部プロセスを開始するために使用する場合、そのstdout/stderrを消費する必要があります。そうしないと、外部プロセスがハングします。

これは、OS がパイプを作成するためです。すべての Unix のような OS と Windows は、この点で同じように動作します。親と子の間に 4K のパイプが作成されます。そのパイプがいっぱいになると (片側が読み取られないため)、書き込みプロセスがブロックされます。

7 つ以上のファイルがある場合、jar.exe が 4K を消費し、その後スタックしたようです。

プロセスの Javadoc:

デフォルトでは、作成されたサブプロセスには独自の端末またはコンソールがありません。すべての標準 I/O (stdin、stdout、stderr) 操作は親プロセスにリダイレクトされ、メソッド getOutputStream()、getInputStream()、および getErrorStream() を使用して取得したストリームを介してアクセスできます。親プロセスは、これらのストリームを使用して、サブプロセスに入力をフィードし、サブプロセスから出力を取得します。一部のネイティブ プラットフォームでは、標準の入力ストリームと出力ストリームに対して限られたバッファー サイズしか提供されないため、サブプロセスの入力ストリームの書き込みまたは出力ストリームの読み取りが迅速に行われないと、サブプロセスがブロックされたり、デッドロックが発生したりする可能性があります。

于 2013-08-29T12:59:50.163 に答える