уменьшить количество открытых файлов в коде Java - PullRequest
5 голосов
/ 24 мая 2011

Привет, у меня есть код, который использует блок

RandomAccessFile file = new RandomAccessFile("some file", "rw");
FileChannel channel = file.getChannel();

// some code
String line = "some data";
ByteBuffer buf = ByteBuffer.wrap(line.getBytes());
channel.write(buf);

channel.close();
file.close();

но особенность приложения заключается в том, что мне нужно сгенерировать большое количество временных файлов, в среднем более 4000 (используется для вставок Hive в многораздельную таблицу).

Проблема в том, что иногда я ловлю исключение

Failed with exception Too many open files

во время работы приложения.

Интересно, есть ли способ сообщить ОС, что файл уже закрыт и больше не используется, почему

channel.close();
file.close();

не уменьшает количество открытых файлов. Есть ли способ сделать это в коде Java?

Я уже увеличил максимальное количество открытых файлов в

#/etc/sysctl.conf:
kern.maxfiles=204800
kern.maxfilesperproc=200000
kern.ipc.somaxconn=8096

Обновление: Я попытался устранить проблему, поэтому я разделил код, чтобы исследовать каждую его часть (создавать файлы, загружать в куст, удалять файлы).

Использование класса «Файл» или «RandomAccessFile» завершается неудачей с исключением «Слишком много открытых файлов».

Наконец я использовал код:

FileOutputStream s = null;
FileChannel c = null;

try {
    s = new FileOutputStream(filePath);
    c = s.getChannel();
    // do writes
    c.write("some data"); 
    c.force(true);
    s.getFD().sync();

} catch (IOException e) {
    // handle exception
} finally {
    if (c != null)
        c.close();
    if (s != null)
        s.close();
}

И это работает с большим количеством файлов (проверено на 20 КБ с размером 5 КБ каждый). Сам код не выдает исключение как предыдущие два класса. Но производственный код (с ульем) все же имел исключение. И кажется, что причиной этого является соединение улья через JDBC. Я буду расследовать дальше.

Ответы [ 3 ]

4 голосов
/ 24 мая 2011

Количество открытых файловых дескрипторов, которые могут использоваться ОС, отличается от количества файловых дескрипторов, которые могут быть открыты процессом. Большинство систем Unix ограничивают количество дескрипторов файлов на процесс. Скорее всего это что-то вроде 1024 файловых дескрипторов для вашей JVM.

a) Вам нужно установить ulimit в оболочке, которая запускает JVM, на более высокое значение. (Что-то вроде 'ulimit -n 4000')

b) Вы должны убедиться, что у вас нет утечек ресурсов, которые мешают завершению ваших файлов.

3 голосов
/ 24 мая 2011

Обязательно используйте блок finally {}.Если по какой-то причине есть исключение, закрытие никогда не произойдет в написанном коде.

0 голосов
/ 24 мая 2011

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

...