【问题标题】:ARM doesn't properly close files, causing too many open files eventuallyARM 没有正确关闭文件,最终导致打开的文件过多
【发布时间】:2014-08-13 06:07:56
【问题描述】:

不确定我的代码的哪一部分确切导致了问题,但是当我开始查明问题时,我注意到当我运行以下代码时打开的文件数会增加。

public synchronized String readStringSync(String basePath,String path){

                if(useLegacy){
                        return readStringLegacy(basePath,path);

                }
                if(!basePath.endsWith("/"))
                        basePath+="/";
                StringBuffer sb = new StringBuffer(420);
                File f= new File(basePath+path);
                if(!f.exists()){
                        return null;
                }
                Charset charset = Charset.forName("UTF-8");
                try (BufferedReader reader = Files.newBufferedReader(Paths.get(f.getAbsolutePath()), charset)) {
                        String line = null;
                        while ((line = reader.readLine()) != null) {
                                sb.append(line+"\r\n");

                        }
                        String ret = sb.toString();

                        if(ret.trim().startsWith("deleted")||ret.trim().equalsIgnoreCase("dummy"))
                                return null;
                        return ret;

                } catch (Exception ex) {
                        ex.printStackTrace();
                        return null;
                }

        }

        public static void main(String... args) throws Exception{

                com.sun.management.UnixOperatingSystemMXBean mxb = (com.sun.management.UnixOperatingSystemMXBean)java.lang.management.ManagementFactory.getOperatingSystemMXBean();
                System.out.println(mxb.getOpenFileDescriptorCount());  //11

                System.out.println(readString("sometestfile"));

                Thread.sleep(1000);

                mxb = (com.sun.management.UnixOperatingSystemMXBean)java.lang.management.ManagementFactory.getOperatingSystemMXBean();
                System.out.println(mxb.getOpenFileDescriptorCount()); //12 wtf


        }

我已经尝试摆脱 File.exists 并用 Files.exists 替换它,但这完全没有任何效果。

由于stackoverflow仍在抱怨缺少细节,这是我正在使用的java版本:

java版本“1.7.0_51” OpenJDK 运行时环境 (IcedTea 2.4.4) (7u51-2.4.4-0ubuntu0.13.04.2) OpenJDK 64 位服务器虚拟机(build 24.45-b08,混合模式)

【问题讨论】:

  • useLegacy 的值是多少?问题可能在readStringLegacy() 内部。
  • 尝试添加 if(true)return null;就在 try 块 => 文件计数保持在 11 之前,所以它是关于 try 块所做的事情的定义
  • 编写一个for 循环,迭代次数大约为 1000 次,并在其中调用相同的 readStringSync() 以读取相同的文件。打印之后打开的文件数。
  • 尝试将等待时间设置为 10 秒 + 以 System.gc() 开头,没有效果
  • icza,还有 12 个打开的文件

标签: java file nio


【解决方案1】:

try-with-resources 语句正确关闭了流/阅读器,您不必担心。

如果您发现文件一直处于打开状态,这不是因为您的代码中存在错误。如果您在系统范围内打开的文件相对较少,您的操作系统甚至 JVM 可能会出于性能原因将它们保持打开一段时间,如果这成为问题,则关闭它们。从您的角度来看,您不能做更多的事情,您可以使用 try-with-resources 语句正确关闭它。

【讨论】:

  • 问题是,整个事情最终开始抛出 FileNotFoundException: too many open files,这是 imo def 需要担心的事情。
  • 您发布的代码不会导致资源泄漏。如果我要追查这个,我会看看你代码中的其他地方。
  • 原来泄漏的主要原因确实在其他地方。打开的文件仍然有一些增加,但要低得多,我不能让它再爆炸成 4 个无花果,所以这也可能是由于一些优化。
【解决方案2】:

去掉 java.nio.parts 并将 try 行替换为: 尝试 (BufferedReader reader = new BufferedReader(new FileReader(basePath+path))){

文件数现在保持在 11 个,但不确定我开始使用 java.nio 解决的问题是否又回来了,也不确定这是否解决了主要问题。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2020-02-15
    • 2016-12-03
    • 1970-01-01
    • 2018-01-27
    相关资源
    最近更新 更多