Я пишу генетический алгоритм, который должен читать/писать много файлов. Тест пригодности для GA вызывает программу под названием gradif
, которая берет файл как входной файл и выдает файл как вывод.java ioexception error = 24 слишком много открытых файлов
Все работает, за исключением случаев, когда размер населения и/или общее количество генераций генетического алгоритма слишком велико. Затем, после стольких поколений, я начинаю получать это: java.io.FileNotFoundException: testfiles/GradifOut29 (Too many open files)
. (Я получаю его много раз для разных файлов, индекс 29
был только тем, который появился в первый раз, когда я его запустил). Это странно, потому что я не получаю ошибку после первого или второго поколения, но после значительного количества поколений, что предполагает, что каждое поколение открывает больше файлов, которые он не закрывает. Но насколько я могу судить, я закрываю все файлы.
Путь код устанавливается функция main()
находится в Population
классе, а Population
класс содержит массив Individuals
. Вот мой код:
Первоначальное создание входных файлов (они с произвольным доступом, так что я мог бы использовать тот же файл на нескольких поколений)
files = new RandomAccessFile[popSize];
for(int i=0; i<popSize; i++){
files[i] = new RandomAccessFile("testfiles/GradifIn"+i, "rw");
}
В конце всей программы:
for(int i=0; i<individuals.length; i++){
files[i].close();
}
Внутри фитнес-теста Individual
«s:
FileInputStream fin = new FileInputStream("testfiles/GradifIn"+index);
FileOutputStream fout = new FileOutputStream("testfiles/GradifOut"+index);
Process process = Runtime.getRuntime().exec ("./gradif");
OutputStream stdin = process.getOutputStream();
InputStream stdout = process.getInputStream();
Затем, позже ....
try{
fin.close();
fout.close();
stdin.close();
stdout.close();
process.getErrorStream().close();
}catch (IOException ioe){
ioe.printStackTrace();
}
Затем, после этого, я добавляю «КОНЕЦ» к файлам, чтобы упростить их синтаксический анализ.
FileWriter writer = new FileWriter("testfiles/GradifOut"+index, true);
writer.write("END");
try{
writer.close();
}catch(IOException ioe){
ioe.printStackTrace();
}
Мой Перенаправление стандартного ввода и стандартный вывод для gradif
взяты из this answer. Я попытался использовать синтаксис try{close()}catch{}
, чтобы увидеть, есть ли проблема с закрытием любого из файлов (там не было), и я получил это от this answer.
Следует также отметить, что тесты пригодности Individual
s проходят одновременно.
UPDATE: Я действительно смог сузить его до звонка exec()
. В моем последнем запуске я впервые столкнулся с проблемой в поколении 733 (с размером населения 100). Почему более ранние поколения прекрасны? Я не понимаю, почему, если нет утечки, алгоритм должен иметь возможность передавать более ранние поколения, но терпеть неудачу на последующих поколениях. И если есть утечка, то откуда это?
UPDATE2: Чтобы выяснить, что здесь происходит, я хотел бы видеть (желательно в режиме реального времени), сколько файлов открылось JVM в любой заданной точке. Есть ли простой способ сделать это?
watch 'lsof -p pid' – Thierry
@Thierry Я сделал это как можно лучше, просто повторю это в терминале. Но можно ли каким-то образом создать то, что покажет количество файлов lsof в режиме реального времени, без меня нужно будет замять клавиши «вверх, входить»? – MattS
Да, это команда watch: «watch. Выполняйте программу периодически, показывая полный выход». интервал по умолчанию составляет 2 секунды, но вы можете его изменить. – Thierry