java ioexception error = 24太多文件打开

时间:2012-07-05 03:07:32

标签: java file io ioexception

我正在编写一个需要读/写大量文件的遗传算法。 GA的适应性测试是调用名为gradif的程序,该程序将文件作为输入并生成文件作为输出。

除非我将遗传算法的种群大小和/或总代数设得太大,否则一切正常。然后,经过这么多代,我开始得到这个: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的健康测试中:

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();
}

然后,我在文件后附加一个'END',以便更容易解析它们。

FileWriter writer = new FileWriter("testfiles/GradifOut"+index, true);
writer.write("END");
try{
   writer.close();
}catch(IOException ioe){
   ioe.printStackTrace();
}

我对gradif的stdin和stdout的重定向来自this answer。我尝试使用try{close()}catch{}语法来查看关闭任何文件是否存在问题(没有),我从this answer获得了该文件。

还应该注意,Individual s'适应性测试同时进行。

更新:我实际上能够将其缩小到exec()电话。在我最近的一次比赛中,我第一次遇到第733代的麻烦(人口规模为100)。为什么前几代人很好?我不明白为什么,如果没有泄漏,算法应该能够通过前几代但在后代失败。如果有泄漏,那么它来自哪里?

UPDATE2:在试图弄清楚这里发生了什么时,我希望能够(最好是实时)看到JVM在任何给定点打开了多少文件。有没有一种简单的方法可以做到这一点?

4 个答案:

答案 0 :(得分:1)

将所有动作放在循环中可能是个好主意:

while(selection_ of_file.hasNext()){
File are new randomFile
open inputFile
open outPufile
read from inputFile
write to outputFile
close inputFile
close outputFile
}

答案 1 :(得分:1)

尝试关闭错误流:

process.getErrorStream().close();

编辑: 实际上你也应该读它,因为错误流上的缓冲区将阻止子进程。

在这里查看StreamGobbler实现: Need sample Java code to run a shellscript

编辑2: 是否有一个人口规模(足够小),无论哪一代,你都没有遇到这个问题?如果是这种情况,您可能不会再泄漏打开的文件/流。

在这种情况下,您有两个解决方案:

  • 重写算法,不要同时打开所有填充文件
  • 或者增加允许打开的文件的最大数量。有关这方面的信息,请参阅here

答案 2 :(得分:0)

你似乎在linux(或类似unix的操作系统)上运行。您可以使用类似“lsof”命令的东西来确定当您收到错误时应用程序打开了哪些文件。

答案 3 :(得分:0)

如果您确定要关闭所有文件等,可以尝试增加ulimit。曾经有一个问题,一个java程序不断进入ulimit上限。增加它解决了我的问题。我认为可能需要重启服务器,因为它是内核参数。