我有一些关于ProcessBuilder的问题。该程序基本上是一个调用命令行脚本的简单包装器。java: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类只是消耗标准输出/ stderr流并在控制台上显示它们的类。
...问题是:为什么地球上的内存消耗会爆炸?
问候,
阿尔诺
编辑:
- 无论我使用的ProcessBuilder或 Runtime.getRuntime.exec(...),该 结果是一样的。
- 爆发往往出现内存由 shell脚本调用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
}
}
}
只是一个猜测:如果StreamConsumer实际上没有使用子进程的文本,那么文本可能会保存在一个不断增大的缓冲区中。 – 2010-09-14 12:01:43
所有stdout&stderr已成功显示在控制台中 – dagnelies 2010-09-14 12:03:10
如何测量内存消耗? _进程正在消耗内存...... JVM?贝壳?排序过程?在没有看到StreamConsumer的情况下,很难知道那里是否存在错误。你确定内存消耗对于进程是私有的还是仅仅是暂时的I/O缓冲区?你真的没有提供太多的东西继续下去。 – 2010-09-14 16:37:01