Отладка проблемы "Слишком много файлов открыта"

Приложение, над которым я работаю, внезапно разбился с помощью

java.io.IOException: ... Too many open files

Как я понимаю, это означает, что файлы открыты, но не закрыты.

Stacktrace, конечно, происходит после факта и может только помочь понять, до какой произошла ошибка.

Что было бы разумным способом поиска в базе кода, чтобы найти эту проблему, которая возникает, когда приложение находится под высокой нагрузкой на нагрузку.

Ответ 1

Я думаю, что лучший способ использовать инструмент, специально предназначенный для этой цели, например этот:

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

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

Кажется, я помню YourKit, также имеющий некоторые возможности для этого, но не могу найти никакой конкретной информации на данный момент.

Ответ 2

  • используйте lsof -p pid, чтобы проверить причину утечки ссылок на файлы;

  • используйте ulimit -n, чтобы увидеть предел открытых ссылок на файлы для одного процесса;

  • проверить какие-либо ресурсы ввода-вывода в вашем проекте, выпущены ли они вовремя? Обратите внимание, что File, Process, Socket (и соединения Http) - все ресурсы ввода-вывода.

    /li >
  • иногда слишком много потоков вызовет эту проблему.

Ответ 3

Что такое ОС? Если это linux/mac, информация в разделе /​​proc должна помочь. В Windows используйте Process Explorer.

Что касается поиска базы кода, возможно, найдите код, который ловит или поднимает IOException. Я думаю, что методы ввода/вывода, которые уже улавливают/повышают это, имеют высокую вероятность необходимости вызова close().

Ответ 4

Вы пытались подключиться к запущенному процессу с помощью jvisualvm (Java 5.0 и более поздних версий в каталоге JDK bin). Вы можете открыть текущий процесс и сделать кучу дампа (который, если у вас есть старший JDK, вам нужно будет анализировать с помощью eclipse или intellij или netbeans et al.).

В JDK 7 кнопка сброса кучи находится на вкладке "Монитор". Он создаст вкладку дампа кучи, суб-вкладку "Классы", которую вы можете проверить и посмотреть, существуют ли какие-либо классы, открывающие файлы, в большом количестве. Еще одна очень полезная функция - сравнение дампа кучи, поэтому вы можете взять ссылочный кучи ссылок, позволить вашему приложению запустить бит, а затем взять еще один куча дампа и сравнить два (ссылка для сравнения находится на вкладке "[heapdump]", которую вы получаете когда вы берете один. В java также есть флаг для получения heapdump при сбое или исключении OOM, вы можете спуститься по этому маршруту, если сравнение дампов кучи не даст вам очевидного класса, который вызывает проблему. Также, "экземпляры", subtab в разбросе дампа кучи покажет вам, что было выделено за время между двумя дампами кучи, которые также могут помочь.

jvisualvm - отличный инструмент, который не получает достаточного количества упоминаний.