[[Java Tips]] * Javaで,子プロセスを使うときの注意点 [#o2ed69de] Javaでは,java.lang.Runtime#exec(...) を使うことで,子プロセスを起動し,外部のプログラムを実行できます. Javaでは,[[java.lang.Runtime>http://java.sun.com/j2se/1.4/ja/docs/ja/api/java/lang/Runtime.html#exec(java.lang.String)]]#exec(...) を使うことで,子プロセスを起動し,外部のプログラムを実行できます. しかし,このメソッドは,使い方を誤るとリソースリークを引き起こします. exec() は,戻り値として,java.lang.Process を返します. Process には,以下の5つのメソッドがあります. [[Process>http://java.sun.com/j2se/1.4/ja/docs/ja/api/java/lang/Process.html]] には,以下の5つのメソッドがあります. - void destroy() -- サブプロセスを終了します。 - int exitValue() -- サブプロセスの終了コードを返します。 - InputStream getErrorStream() -- サブプロセスのエラーストリームを取得します。 - InputStream getInputStream() -- サブプロセスの入力ストリームを取得します。 - OutputStream getOutputStream() -- サブプロセスの出力ストリームを取得します。 - int waitFor() -- 必要な場合に、この Process オブジェクトが表すプロセスが終了するまで現在のスレッドを待機させます。 問題となるのは,getErrorStream, getInputStream, getOutputStream の3つです. これらは,それぞれ,InputStreamとOutputStream を返し,子プロセスの標準入出力と標準エラー出力を読み書き出来ます. 標準入出力や標準エラー出力にアクセスしなければ用がないのですが,用がない場合でも,明示的にすべてのストリームをcloseしてやらないと,ファイルディスクリプタを解放せず,保持し続けます. 数回実行する程度なら問題が表面化しませんが,繰り返し実行すると,最後にはファイルディスクリプタが足りなくなり,"Too many open files"というメッセージとともに,例外が発生し,ファイルが開けなくなります. 子プロセス呼び出し後は,必ず,ストリームを閉じなければなりません. 例えば,次のようになります. Process process = null; try { process = Runtime.getRuntime().exec("someone_command"); process.waitFor(); } finally { if(process != null) { process.getErrorStream().close(); process.getInputStream().close(); process.getOutputStream().close(); process.destroy(); } }