IOException: слишком много открытых файлов

Я пытаюсь отладить утечку дескриптора файла в веб-приложении Java, работающем в Jetty 7.0.1 в Linux.

Приложение успешно работало в течение месяца или около того, когда запросы начали отказывать из-за слишком большого количества открытых файлов, и Jetty пришлось перезапустить.

java.io.IOException: Cannot run program [external program]: java.io.IOException: error=24, Too many open files
    at java.lang.ProcessBuilder.start(ProcessBuilder.java:459)
    at java.lang.Runtime.exec(Runtime.java:593)
    at org.apache.commons.exec.launcher.Java13CommandLauncher.exec(Java13CommandLauncher.java:58)
    at org.apache.commons.exec.DefaultExecutor.launch(DefaultExecutor.java:246)

Сначала я подумал, что проблема связана с кодом, запускающим внешнюю программу, но он использует commons-exec. и не вижу в этом ничего плохого:

CommandLine command = new CommandLine("/path/to/command")
    .addArgument("...");
ByteArrayOutputStream errorBuffer = new ByteArrayOutputStream();
Executor executor = new DefaultExecutor();
executor.setWatchdog(new ExecuteWatchdog(PROCESS_TIMEOUT));
executor.setStreamHandler(new PumpStreamHandler(null, errorBuffer));
try {
    executor.execute(command);
} catch (ExecuteException executeException) {
    if (executeException.getExitValue() == EXIT_CODE_TIMEOUT) {
        throw new MyCommandException("timeout");
    } else {
        throw new MyCommandException(errorBuffer.toString("UTF-8"));
    }
}

В списке открытых файлов на сервере я вижу большое количество FIFO:

# lsof -u jetty
...
java    524 jetty  218w  FIFO        0,6      0t0 19404236 pipe
java    524 jetty  219r  FIFO        0,6      0t0 19404008 pipe
java    524 jetty  220r  FIFO        0,6      0t0 19404237 pipe
java    524 jetty  222r  FIFO        0,6      0t0 19404238 pipe

когда Jetty запускается, есть всего 10 FIFO, через несколько дней их сотни.

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


person Mirko N.    schedule 11.01.2010    source источник
comment
Добавлен код запуска внешней программы.   -  person Mirko N.    schedule 11.01.2010
comment
В качестве дополнительного источника информации netstat -anp --tcp|grep ‹PID› --color может быть   -  person zaletniy    schedule 12.09.2011
comment
добавить блок finally после try-catch и закрыть все потоки. Возможно, потоки не закрываются должным образом, и поэтому вы получили эту ошибку. Также обратите внимание, что Linux обрабатывает количество открытых подключений в открытых файлах, поэтому проверьте ваш код на наличие открытого подключения.   -  person Yogesh Kulkarni    schedule 16.05.2014
comment
См. также stackoverflow.com/questions/4289447/java-too -много-открытых-файлов   -  person Raedwald    schedule 14.03.2019


Ответы (6)


Проблема связана с вашим Java-приложением (или используемой библиотекой).

Во-первых, вы должны прочитать все результаты (Google для StreamGobbler) и быстро!

Javadoc говорит:

Родительский процесс использует эти потоки для подачи входных данных и получения выходных данных из подпроцесса. Поскольку некоторые собственные платформы предоставляют только ограниченный размер буфера для стандартных входных и выходных потоков, неспособность быстро записать входной поток или прочитать выходной поток подпроцесса может привести к блокировке подпроцесса и даже взаимоблокировке.

Во-вторых, waitFor() ваш процесс для завершения. Затем вы должны закрыть потоки ввода, вывода и ошибок.

Наконец destroy() ваш процесс.

Мои источники:

person ofavre    schedule 11.05.2011
comment
Это правильный ответ, который действительно содержит полезную информацию. - person Vivin Paliath; 08.04.2014
comment
Вам не нужно уничтожать процесс, если waitFor() удалось. Процесс уже завершен. - person user207421; 14.09.2015

Поскольку вы работаете в Linux, я подозреваю, что у вас заканчиваются файловые дескрипторы. Проверьте улимит. Вот статья, описывающая проблему: http://www.cyberciti.biz/faq/linux-increase-the-maximum-number-of-open-files/

person Community    schedule 11.01.2010
comment
Это может дать вам до 2 месяцев работы! (Это в лучшем случае пластырь.) - person Greg D; 11.01.2010
comment
Вы повторили симптом, но не настоящее лекарство. - person Carl Smotricz; 11.01.2010
comment
На самом деле я поднял лимит в /etc/security/limits.conf уже по другим причинам. - person Mirko N.; 11.01.2010
comment
По крайней мере, это может решить нашу проблему. Приложение (стороннее) открывает более 1024. Утечки НЕТ, но просто ограничение слишком низкое. Установка ограничения на 65 535, как предлагается в этой . Похоже проблема ушла. - person Devs love ZenUML; 09.02.2017

Помимо изучения основных причин таких проблем, как утечка файлов и т. д., чтобы законно увеличить лимит «открытых файлов» и сохранить его при перезагрузке, рассмотрите возможность редактирования

/etc/security/limits.conf

добавив что-то вроде этого

jetty soft nofile 2048
jetty hard nofile 4096

где «причал» — это имя пользователя в данном случае. Для получения дополнительной информации о limit.conf см. http://linux.die.net/man/5/limits.conf

выйдите из системы, а затем войдите снова и запустите

ulimit -n

чтобы убедиться, что изменение произошло. Новые процессы этого пользователя теперь должны соответствовать этому изменению. Эта ссылка описывает, как применить ограничение к уже запущенным процессам, но я не пробовал.

Ограничение по умолчанию 1024 может быть слишком низким для больших приложений Java.

person Rami Jaamour    schedule 31.07.2014

Не знаю природу вашего приложения, но я видел, как эта ошибка проявлялась несколько раз из-за утечки пула соединений, так что это стоит проверить. В Linux сокетные соединения используют файловые дескрипторы, а также файлы файловой системы. Просто мысль.

person alasdairg    schedule 11.01.2010

Вы можете справиться с fds самостоятельно. Exec в java возвращает объект Process. Периодически проверяйте, запущен ли процесс. После завершения закройте потоки процессов STDERR, STDIN и STDOUT (например, proc.getErrorStream.close()). Это уменьшит утечки.

person allenjsomb    schedule 24.03.2011

Эта проблема возникает, когда вы записываете данные во многие файлы одновременно, а ваша операционная система имеет фиксированный лимит открытых файлов. В Linux вы можете увеличить лимит открытых файлов.

https://www.tecmint.com/increase-set-open-file-limits-in-linux/

Как изменить количество открытых ограничение на количество файлов в Linux?

person Vpn_talent    schedule 06.06.2018