JavaのProcessBuilderの実行結果が欠損する問題の対策

下記のようなKotlinのサンプルコードを使えば、コマンドの実行結果をある程度の結果を受け取れる事ができるが、厳密にすべての出力を得ることができなかった。

これはプロセスの処理が完了していない状態でreader.readLine()の部分でnullが返ることで、処理が完了していないのにストリームの読み込みを終了してしまうことが原因だった。

class Example1(processBuilder: ProcessBuilder) {
var input = StringBuilder()
init {
val process = processBuilder.start()
this.loadInputStream(process)
process.waitFor()
}
private fun loadInputStream(it: Process) {
val reader = BufferedReader(InputStreamReader(it.inputStream))
Thread {
reader.use { reader ->
while (reader.readLine() != null) {
input.append(reader.readLine() + "\n")
}
}
}.start()
}
}

下記のように処理の終了を待ってから明示的にループを停止することで取りこぼしがなくなりました。

class Example2(processBuilder: ProcessBuilder) {
var running = true
var input = StringBuilder()
init {
val process = processBuilder.start()
this.loadInputStream(process)
process.waitFor()
this.running = false
}
private fun loadInputStream(it: Process) {
val reader = BufferedReader(InputStreamReader(it.inputStream))
Thread {
reader.use { reader ->
while (running) {
input.append(reader.readLine() + "\n")
}
}
}.start()
}
}

この現象は一瞬で処理結果が返ってくるものから、長い時間かけて緩やかに結果を返すジョブに対しても同じように発生しました。

コメントを残す

メールアドレスが公開されることはありません。 * が付いている欄は必須項目です

CAPTCHA