ProcessBuilderに関していくつか問題があります。プログラムは基本的に、コマンドラインスクリプトを呼び出す単純なラッパーです。
ターミナルを介してスクリプトを単独で実行する場合、メモリ消費量は2G未満にとどまります。Javaラッパーを介してスクリプトを実行すると、メモリ消費量が爆発的に増加し、8Gでさえすぐにいっぱいになり、メモリ不足エラーが発生します。
プロセスを起動するためのコードは単純です。
public static int execute(String command) throws IOException
{
System.out.println("Executing: " + command);
ProcessBuilder pb = new ProcessBuilder(command.split(" +"));
Process p = pb.start();
// display any output in stderr or stdout
StreamConsumer stderr = new StreamConsumer(p.getErrorStream(), "stderr");
StreamConsumer stdout = new StreamConsumer(p.getInputStream(), "stdout");
new Thread(stderr).start();
new Thread(stdout).start();
try {
return p.waitFor();
} catch (InterruptedException e) {
throw new RuntimeException(e);
}
}
StreamConsumerクラスは、単にstdout / stderrストリームを消費し、それらをコンソールに表示するクラスです。
...問題は、いったいなぜメモリ消費が爆発するのかということです。
よろしく、
アルノー
編集:
- ProcessBuilderとRuntime.getRuntime.exec(...)のどちらを使用しても、結果は同じです。
- メモリバーストは、次のシェルスクリプトによって呼び出されるUNIXの「ソート」中に表示される傾向があります。
sort big-text-file > big-text-file.sorted
ジム・ギャリソンの要求に応じて2を編集します。
わかりました。これは、かなり単純なため省略したStreamConsumerクラスです。
class StreamConsumer implements Runnable
{
InputStream stream;
String descr;
StreamConsumer(InputStream stream, String descr) {
this.stream = stream;
this.descr = descr;
}
@Override
public void run()
{
String line;
BufferedReader brCleanUp =
new BufferedReader (new InputStreamReader (stream));
try {
while ((line = brCleanUp.readLine ()) != null)
System.out.println ("[" + descr + "] " + line);
brCleanUp.close();
} catch (IOException e) {
// TODO: handle exception
}
}
}