ソフトウェアエンジニア現役続行

雑多なことを綴ります

Process.destroy()の前に必ずすべてのストリームをcloseすること

次のような間違いを含んだコードがあります。


// 同じようなことがRuntime.exec(...)でも起こる
ProcessBuilder pb = new ProcessBuilder(args);
Process proc = pb.start();
InputStream in = proc.getInputStream();
// ・・・ここでスレッドのストリームから読んで処理をする
proc.waitFor();

// ・・・最後に、finallyブロックで「InputStreamを」クローズして、プロセスを終了する(不十分)
in.close();
proc.destroy();


プロセスを作成して、ストリームをキャプチャして、最後にそのストリームをクローズしています。ごく一般的な考え方によるコードだと思います。

しかし、これは間違いです。上記コードをループで繰り返すと、IOException がスローされ、'Too many open files'だと言われます。

これは、ProcessBuilderを使用するとバックグラウンドでInputStream, OutputStream, ErrorStreamが勝手にオープンされるため、全てのストリームをクローズしないとリソース不足に陥るからでした。

この問題を解決するには、次のように全てのストリームをちゃんとクローズしなくてはなりません。下のほうの2行が追加部分です。


ProcessBuilder pb = new ProcessBuilder(args);
Process proc = pb.start();
InputStream in = proc.getInputStream();
// ・・・ここでスレッドのストリームから読んで処理をする
proc.waitFor();

// ・・・最後に、finallyブロックで「全ての」ストリームをクローズする
in.close();
proc.getOutputStream().close(); (←追加)
proc.getErrorStream().close(); (←追加)
proc.destroy();


ちなみにProcess.destroy()のjavadocには次のような説明しかありません。これでは同じような過ちをする人があとを絶たないでしょう・・・。

サブプロセスを終了します。この Process オブジェクトが表すサブプロセスは強制終了されます。

javadocを修正するようにいくつかのバグレポートで言及されています。早く反映されると良いのですが・・・。