Слишком много открытых файлов: сколько из них открыто, каковы они и сколько можно открыть JVM
Я получаю это исключение в Java:
java.io.FileNotFoundException: (Too many open files)
Я ищу способы устранить эту проблему.
Эта ошибка, очевидно, указывает на то, что JVM выделила слишком много дескрипторов, и базовая ОС не позволит ей иметь больше. Либо у меня есть утечка где-то с неправильно закрытыми соединениями/потоками.
Этот процесс работает в течение нескольких дней без остановок и, в конце концов, выдает исключение. Это повторяется через 12-14 дней.
Как вы сражаетесь с этим? Есть ли способ получить список выделенных дескрипторов в JVM или отслеживать, когда он наберет определенную сумму? Я бы хотел, чтобы они напечатали и посмотрели, как он растет и когда. Я не могу использовать профилировщик, потому что это производственная система и трудно воспроизвести ее в процессе разработки. Любое предложение?
Я контролирую размер свободной кучи и поднимаю "будильник", когда он приближается к 1% от общего количества, указанного в -Xmx. Я также знаю, что если число моих потоков превышает 500, то что-то определенно выходит из-под контроля. Теперь есть способ узнать, что моя JVM выделяет слишком много дескрипторов из ОС и не возвращает их, например. сокеты, открытые файлы и т.д. Если бы я знал это, я знал бы, где искать и когда.
Ответы
Ответ 1
Вы не сказали, на какой ОС вы работаете, но если вы работаете в Linux, вы можете использовать команду lsof
lsof -p <pid of jvm>
Это будет список всех файлов, открытых JVM. Или, если вы работаете в Windows, вы можете Process Explorer, который покажет все открытые файлы для всех процессов.
Выполнение этого, мы надеемся, позволит вам сузить, какой бит кода хранит файлы.
Ответ 2
Поскольку вы находитесь в Linux, я бы предположил, что вы проверяете /proc -Filesystem. Внутри proc вы найдете папку с PID вашего процесса, содержащую папку calld 'fd'. Если ваш идентификатор процесса равен 1234, путь будет
/proc/1234/fd
Внутри этой папки вы найдете ссылки на все открытые файлы (сделайте "ls -l" ). Обычно вы можете указать по имени файла, который может открыть библиотека/код и не закрыть файл.
Ответ 3
Вы можете изменить предел открытых файлов, добавив следующее к /etc/security/limits.conf
:
* soft nofile 2048 # Set the limit according to your needs
* hard nofile 2048
Затем вы можете перезагрузить конфигурацию, используя sysctl -p
в оболочке. Проверьте эту статью.
Просто для полноты вы можете проверить, каков текущий предел для открытых файлов, используя: ulimit -n
Ответ 4
Итак, полный ответ (я комбинировал ответы от @phisch и @bramp). Если вы хотите проверить все процессы, вы должны использовать sudo
. Также неплохо сохранить результат в файле - lsof не является дешевым + этот файл может быть полезен для дальнейшего изучения.
sudo lsof > lsof.log
Показать плохих парней (с сообщением UPDATE от @Arun):
cat lsof.log | awk '{print $1 " " $2 " " $5}' | sort | uniq |awk '{ print $2 " " $1; }' | sort -rn | uniq -c | sort -rn | head -5
2687 114970 java
131 127992 nginx
109 128005 nginx
105 127994 nginx
103 128019 nginx
Сохраните также список файловых дескрипторов:
sudo ls -l /proc/114970/fd > fd.log
Показать верхние открытые файлы:
cat fd | awk '{ print $11 }' | sort -rn | uniq -c | sort -rn | head -n20