45
43

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

More than 5 years have passed since last update.

Java の外部プロセスが返って来ない場合の対処方法

Last updated at Posted at 2014-02-27

Java で外部プロセスを起動する際は ProcessBuilder クラスを使いますが、
たまに処理が戻ってこない場合があります。

そんな場合に原因として考えられるのは、標準出力または標準エラー出力にバッファが溜まってしまっているという理由です。

例えば以下のコードの場合、標準エラー出力のバッファがいっぱいになっていた場合は
proc.getInputStream() から処理が返って来なくなります。

String[] cmds = {"./foo.sh"};

ProcessBuilder pb = new ProcessBuilder(cmds);
Process proc = pb.start();

String str;
BufferedReader brstd = new BufferedReader(new InputStreamReader(proc.getInputStream()));
while((str = brstd.readLine()) != null) {
	trace(str);
}
brstd.close();

とはいえ、以下のようなコードにすると、今度は標準出力のバッファが溜まってしまった場合に
proc.getErrorStream() から処理が返って来なくなります。

String[] cmds = {"./foo.sh"};

ProcessBuilder pb = new ProcessBuilder(cmds);
Process proc = pb.start();

String str;

BufferedReader brerr = new BufferedReader(new InputStreamReader(proc.getErrorStream()));
while((str = brerr.readLine()) != null) {
	trace(str);
}
brerr.close();

BufferedReader brstd = new BufferedReader(new InputStreamReader(proc.getInputStream()));
while((str = brstd.readLine()) != null) {
	trace(str);
}
brstd.close();

標準出力とエラー出力が混ざってもOKという場合であれば、
redirectErrorStream が有効かと思います。

String[] cmds = {"./foo.sh"};

ProcessBuilder pb = new ProcessBuilder(cmds);
Process proc = pb.start();

// 標準出力と標準エラー出力をMIX
pb.redirectErrorStream(true);

String str;
BufferedReader brstd = new BufferedReader(new InputStreamReader(proc.getInputStream()));
while((str = brstd.readLine()) != null) {
	trace(str);
}
brstd.close();

これで、 proc.getInputStream() から処理が返って来なくなることはなくなります。

どうしても標準出力と標準エラー出力を分けなければいけない場合は、
片方を別スレッドで処理すればなんとかなります。
(あまり美しくないですが・・・)

String[] cmds = {"./foo.sh"};

ProcessBuilder pb = new ProcessBuilder(cmds);
final Process proc = pb.start();

//エラー出力は別スレッドで吐き出す
Thread th = new Thread(new Runnable() {
	@Override
	public void run() {
		String str;
		BufferedReader brerr = new BufferedReader(new InputStreamReader(proc.getErrorStream()));
		try {
			while((str = brerr.readLine()) != null) {
				trace(str);
			}
		} catch (IOException e) {
			e.printStackTrace();
		} finally {
			try {
				brerr.close();
			} catch (IOException e) {
				e.printStackTrace();
			}
		}
	}
});
th.start();

String str;
BufferedReader brstd = new BufferedReader(new InputStreamReader(proc.getInputStream()));
while((str = brstd.readLine()) != null) {
	trace(str);
}
brstd.close();


45
43
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
45
43

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?