Подтвердить что ты не робот

Слишком много открытых файлов: сколько из них открыто, каковы они и сколько можно открыть JVM

Я получаю это исключение в Java:

java.io.FileNotFoundException: (Too many open files) 

Я ищу способы устранить эту проблему.

Эта ошибка, очевидно, указывает на то, что JVM выделила слишком много дескрипторов, и базовая ОС не позволит ей иметь больше. Либо у меня есть утечка где-то с неправильно закрытыми соединениями/потоками.

Этот процесс работает в течение нескольких дней без остановок и, в конце концов, выдает исключение. Это повторяется через 12-14 дней.

Как вы сражаетесь с этим? Есть ли способ получить список выделенных дескрипторов в JVM или отслеживать, когда он наберет определенную сумму? Я бы хотел, чтобы они напечатали и посмотрели, как он растет и когда. Я не могу использовать профилировщик, потому что это производственная система и трудно воспроизвести ее в процессе разработки. Любое предложение?

Я контролирую размер свободной кучи и поднимаю "будильник", когда он приближается к 1% от общего количества, указанного в -Xmx. Я также знаю, что если число моих потоков превышает 500, то что-то определенно выходит из-под контроля. Теперь есть способ узнать, что моя JVM выделяет слишком много дескрипторов из ОС и не возвращает их, например. сокеты, открытые файлы и т.д. Если бы я знал это, я знал бы, где искать и когда.

4b9b3361

Ответ 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