java.io.FileNotFoundException: /tmp/(打开的文件太多)
java.io.FileNotFoundException: /tmp/ (Too many open files)
我在 Java EE 中有一个休息服务,出于一些奇怪的向后兼容性原因,我必须 return 在 URL 请求中添加一些行后的 .mdb 文件.
起初我只是打开一个 mdb 文件,清除其中的所有行,写入我的行并将其 returned 给调用者,但是我意识到 .mdb 一直以这种方式增长,因为 Access 没有在删除时清除行,但只删除它,我使用的库 (Jackcess) 不支持完全清除行。
所以我转而使用 java.io.File.createTempFile() 和 return 创建一个空的 .mdb 文件的副本,但是仍然有一个指向 /tmp/ 文件夹中文件的悬空指针,并且几天后我得到一个
java.io.FileNotFoundException: /tmp/tmpdb.mdb04949499 (Too many open files)
到目前为止我找到的唯一解决方案是:
- 将 MAX_FILE_HANDLES_FOR_READ_ENDS_MAP 设置为非常高的数字(这只会推迟问题)
- 删除临时文件,但是这是不可行的,因为我 return 它来自一个函数,一旦 return 我失去了对指针的控制。
低于我目前拥有的:
GET
@Path("/get/database/{filename}")
@Produces("application/jet")
public StreamingOutput getDatabase(@PathParam("filename") String fileName)
{
//access files increase indefinitely in size because deleted rows are simply marked "deleted" and not removed
//so we create a temporary file equal to the template .mdb file and use it instead
java.io.File myDBFile = null;
try
{
java.io.File templateDBFile = new java.io.File(url + "resources/clean_tmpdb.mdb");
myDBFile = java.io.File.createTempFile("tmpdb", ".mdb");
myDBFile.deleteOnExit(); //useless hint
FileChannel src = new FileInputStream(templateDBFile).getChannel();
FileChannel dest = new FileOutputStream(myDBFile).getChannel();
dest.transferFrom(src, 0, src.size());
}
catch (IOException ex)
{
Logger.getLogger(FileResource.class.getName()).log(Level.SEVERE, null, ex);
}
finally
{
if (src != null)
{
try
{
src.close();
}
catch (IOException ex)
{
Logger.getLogger(FileResource.class.getName()).log(Level.SEVERE, null, ex);
}
}
if (dest != null)
{
try
{
dest.close();
}
catch (IOException ex)
{
Logger.getLogger(FileResource.class.getName()).log(Level.SEVERE, null, ex);
}
}
/* work on the file inserting rows */
return new FileStreamingOutput(myDBFile);
}
编辑:发现了一个类似的问题,接受的答案含糊不清:How to delete file after REST response,接受的答案是"just write directly to the output stream contained in the Response."
您没有关闭 src
或 dest
。为了确保它们被关闭,在 finally
块中关闭它们,或者使用 try-with-resources 语法。
return new FileStreamingOutput(myDBFile);
/* here I should call myDBFile.close(); and myDBFile.delete(); */
这里不能调用myDBFile.close()
,因为没有这样的方法。您也不能调用 myDBFile.delete()
,否则调用者将收到不存在的 File
。如果 File
需要删除,调用者将不得不这样做。您提出的要求没有意义。
我在 Java EE 中有一个休息服务,出于一些奇怪的向后兼容性原因,我必须 return 在 URL 请求中添加一些行后的 .mdb 文件.
起初我只是打开一个 mdb 文件,清除其中的所有行,写入我的行并将其 returned 给调用者,但是我意识到 .mdb 一直以这种方式增长,因为 Access 没有在删除时清除行,但只删除它,我使用的库 (Jackcess) 不支持完全清除行。
所以我转而使用 java.io.File.createTempFile() 和 return 创建一个空的 .mdb 文件的副本,但是仍然有一个指向 /tmp/ 文件夹中文件的悬空指针,并且几天后我得到一个
java.io.FileNotFoundException: /tmp/tmpdb.mdb04949499 (Too many open files)
到目前为止我找到的唯一解决方案是:
- 将 MAX_FILE_HANDLES_FOR_READ_ENDS_MAP 设置为非常高的数字(这只会推迟问题)
- 删除临时文件,但是这是不可行的,因为我 return 它来自一个函数,一旦 return 我失去了对指针的控制。
低于我目前拥有的:
GET
@Path("/get/database/{filename}")
@Produces("application/jet")
public StreamingOutput getDatabase(@PathParam("filename") String fileName)
{
//access files increase indefinitely in size because deleted rows are simply marked "deleted" and not removed
//so we create a temporary file equal to the template .mdb file and use it instead
java.io.File myDBFile = null;
try
{
java.io.File templateDBFile = new java.io.File(url + "resources/clean_tmpdb.mdb");
myDBFile = java.io.File.createTempFile("tmpdb", ".mdb");
myDBFile.deleteOnExit(); //useless hint
FileChannel src = new FileInputStream(templateDBFile).getChannel();
FileChannel dest = new FileOutputStream(myDBFile).getChannel();
dest.transferFrom(src, 0, src.size());
}
catch (IOException ex)
{
Logger.getLogger(FileResource.class.getName()).log(Level.SEVERE, null, ex);
}
finally
{
if (src != null)
{
try
{
src.close();
}
catch (IOException ex)
{
Logger.getLogger(FileResource.class.getName()).log(Level.SEVERE, null, ex);
}
}
if (dest != null)
{
try
{
dest.close();
}
catch (IOException ex)
{
Logger.getLogger(FileResource.class.getName()).log(Level.SEVERE, null, ex);
}
}
/* work on the file inserting rows */
return new FileStreamingOutput(myDBFile);
}
编辑:发现了一个类似的问题,接受的答案含糊不清:How to delete file after REST response,接受的答案是"just write directly to the output stream contained in the Response."
您没有关闭 src
或 dest
。为了确保它们被关闭,在 finally
块中关闭它们,或者使用 try-with-resources 语法。
return new FileStreamingOutput(myDBFile);
/* here I should call myDBFile.close(); and myDBFile.delete(); */
这里不能调用myDBFile.close()
,因为没有这样的方法。您也不能调用 myDBFile.delete()
,否则调用者将收到不存在的 File
。如果 File
需要删除,调用者将不得不这样做。您提出的要求没有意义。