Проблема с конструктором процессов waitFor () и ограничения на открытие файлов

Я унаследовал код:

Process p = new ProcessBuilder("/bin/chmod", "777", path).start();
p.waitFor();

По сути, существует какая-то древняя и очень вудуская причина для хранения пар ключ / значение на диске в виде файлов. Я действительно не хочу вдаваться в подробности.

Однако у меня осталось несколько исключений ввода-вывода:

Exception :Cannot run program "/bin/chmod": java.io.IOException: error=24, Too many open files
Message: Cannot run program "/bin/chmod": java.io.IOException: error=24, Too many open files

И под кучей я имею в виду в области 10k - миллионов

У меня такое ощущение, что вызов waitFor должен был остановить их, ожидая, пока процесс завершит его и выйдет обратно, однако я думаю, что chmod возвращает результат до того, как файл будет фактически закрыт. Кто-нибудь знает, может ли это быть причиной этих исключений?

Другая моя склонность заключается в том, что открытие и закрытие тысяч файлов не происходит достаточно быстро на конце java и что происходит что-то еще, возможно, что-то в этом роде, есть какая-то форма файлового буфера, которая не очищается, когда Вызывается fw.close ().

Я новичок в java, и это было чертовски странно, что меня поставило в тупик. (к счастью, приложение все еще как-то работает ... после того, как выплюнул очень большой файл журнала)

Может ли кто-нибудь еще придумать способ обойти это, очистив буферы или увеличив лимит открытия файлов до чего-то, где jvm может идти в ногу с собой (при условии, что это проблема)


person Louis    schedule 15.07.2009    source источник
comment
Какая у вас целевая ОС (и версия). См. Это: unix.derkeiler.com/Newsgroups/comp .unix.solaris / 2007-02 /   -  person Ryan Fernandes    schedule 15.07.2009
comment
debian, похоже, из uname он очищен. будет последняя стабильная версия.   -  person Louis    schedule 16.07.2009


Ответы (4)


Я предполагаю, что вы запускаете эти команды chmod в цикле - иначе я не понимаю, почему вы получаете так много исключений. Возможно, вы попали в тупик, потому что не читаете вывод порожденных процессов. Это определенно кусало меня еще до ProcessBuilder, Runtime.exec() дней.

Измените фрагмент кода на приведенный выше шаблон:

try {
    ProcessBuilder pb = new ProcessBuilder("/bin/chmod", "777", path);    
    pb.redirectErrorStream(true); // merge stdout, stderr of process

    Process p = pb.start();
    InputStreamReader isr = new  InputStreamReader(p.getInputStream());
    BufferedReader br = new BufferedReader(isr);

    String lineRead;
    while ((lineRead = br.readLine()) != null) {
        // swallow the line, or print it out - System.out.println(lineRead);
    }

    int rc = p.waitFor();
    // TODO error handling for non-zero rc
}
catch (IOException e) {
    e.printStackTrace(); // or log it, or otherwise handle it
}
catch (InterruptedException ie) {
    ie.printStackTrace(); // or log it, or otherwise handle it
} 

(кредит: этот сайт) и посмотрите, поможет ли это ситуации.

person Vinay Sajip    schedule 15.07.2009
comment
Пробовал, возникают те же исключения - person Louis; 16.07.2009
comment
Думаю, я решил это проверить свой ответ через несколько минут - просто жду тестов, чтобы проверить - person Louis; 16.07.2009
comment
Хорошо, выбрал ваш в качестве ответа, так как он нуждался в этом в решении, проверьте, что мой пост будет включать необходимые дополнительные строки. - person Louis; 16.07.2009

Спасибо за помощь, ребята, это должно решить массу странностей, происходящих из-за этого где-то еще.

Используя ваш пример (Vinay) и закрытия потока:

try{ 
  fw.close();

  ProcessBuilder pb = new ProcessBuilder("/bin/chmod", "777", path);

  pb.redirectErrorStream(true); // merge stdout, stderr of process
  p = pb.start();

  InputStreamReader isr = new  InputStreamReader(p.getInputStream());
  BufferedReader br = new BufferedReader(isr);

  String lineRead;
  while ((lineRead = br.readLine()) != null) {
    // swallow the line, or print it out - System.out.println(lineRead);
  }

} catch (Exception ioe) {
  Logger.logException(Logger.WARN, ioe.getMessage(), ioe);
} finally {
  try {
    p.waitFor();//here as there is some snipped code that was causing a different
                // exception which stopped it from getting processed

    //missing these was causing the mass amounts of open 'files'
    p.getInputStream().close();
    p.getOutputStream().close();
    p.getErrorStream().close(); 

  } catch (Exception ioe) {
    Logger.logException(Logger.WARN, ioe.getMessage(), ioe);
  }
}

Позаимствовал идею из сообщения < / а>.

person Louis    schedule 15.07.2009
comment
примечание: все еще не имеет смысла, почему наличие waitFor и закрытие входных потоков не сработает, но я думаю, что это java ... - person Louis; 16.07.2009
comment
Хороший улов, Джим, но я все еще вижу проблему в твоем finally. Я думаю, вам нужно, чтобы каждый из close вызовов был отдельным catch, иначе, если при выполнении p.getInputStream.close() возникнет исключение, вы не сможете закрыть остальные. Может показаться, что проблема исчезла сейчас, но может вернуться позже. - person Vinay Sajip; 16.07.2009
comment
Вам действительно нужно закрыть и поток ввода, и поток ошибок, даже если они объединены с redirectErrorStream? И действительно ли вам нужно закрывать выходной поток, даже если вы его никогда не использовали? - person Rob Kennedy; 05.05.2016
comment
Вам нужно будет проверить оба и выяснить. Этот пост действительно старый, я не думаю, что код вообще жив. - person Louis; 05.05.2016

Кажется маловероятным, что процесс действительно завершится без закрытия файлов. Может ли это происходить в очень большом количестве потоков? Или, возможно, некоторые из них на самом деле не завершаются (т. Е. В некоторых случаях зависает на waitFor)?

В противном случае, я думаю, вы застрянете с увеличением лимита открытых файлов. Предполагая, что это Unix-подобная система, вероятно, вы ищете команду «ulimit».

person jsight    schedule 15.07.2009

Если вы используете JAVA 6, вы также можете попробовать новые сеттеры (для чтения, записи, выполнения) для объекта File. Может быть медленнее, но должно работать.

person Ryan Fernandes    schedule 15.07.2009