Java: ProcessBuilder делает боров памяти - PullRequest
5 голосов
/ 14 сентября 2010

У меня есть некоторые проблемы, касающиеся 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 и отображает их на консоли.

... вопрос в том: с какой стати взрывается потребление памяти?

С уважением,
Arnaud

Edit:

  • Использую ли я 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
        }
    }
}

Ответы [ 2 ]

2 голосов
/ 23 июня 2011

если вы измените свою команду следующим образом: sort -o big-text-file.sorted big-text-file

всегда ли это то же самое?

0 голосов
/ 15 октября 2011

Может быть потому, что эти StreamConsumer потоки не являются демонами, поэтому они не умирают и не собирают мусор при возврате ваших процессов? Вы можете попробовать:

//...  
final StreamConsumer stderr = new StreamConsumer(p.getErrorStream(), "stderr");
final StreamConsumer stdout = new StreamConsumer(p.getInputStream(), "stdout");
final Thread stderrThread = new Thread(stderr);
final Thread stdoutThread = new Thread(stdout);
stderrThread.setDaemon(true);
stdoutThread.setDaemon(true);
stderrThread.start();
stdoutThread.start();
//...

Такое поведение происходит при однократном вызове или после многократного выполнения?

...