You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何在Eclipse中避免调用System.gc()?解决文件占用问题

问题描述

核心问题:BufferedReader未正确释放资源,导致项目其他模块出错。删除System.gc()后,下次尝试替换文件时会出现**“文件正被另一进程占用”**的错误。我尝试在代码中加入br.close()来解决,但问题仍存在。

相关代码

public double fileGame(ArrayList<String> d) {
    System.out.println("file 1");
    String line;
    System.out.println(d.size());
    
    try {
        Month Month = LocalDate.now().getMonth();
        String m = Month.toString().substring(0,3);
        System.out.println(m);
        int yr = LocalDate.now().getYear();
        String fin = m+" "+yr;
        Path gamepath = Paths.get(game);
        String dabe = "C:\\Users\\OneDrive\\Documents\\financials\\tempread.csv";
        Path read = Paths.get(dabe);
        Files.copy(gamepath, read);
        Path New = Paths.get(dabe);
        Files.deleteIfExists(New);
        Files.copy(gamepath,New);
        BufferedReader br = new BufferedReader(new FileReader(dabe));
        boolean cont = false; //checks if Game id is in paid list
        int i = 0;
        double paidAmount=0;
        while ((line = br.readLine() ) != null) {
            System.out.println(line+"li");
            String[] values = line.split(",");
            System.out.println(values.length+" size") ;
            String id = values[0];
            String date = values[1];
            String loc = values[2];
            Double amount = Double.parseDouble(values[3]);
            String by = values[4];
            String paid = values[5];
            Game g = new Game(id,date,loc,amount,by,paid);
            records.add(g);
        }
        while (i<records.size()&&d.size()>0) {
            System.out.println("Game Paid: "+records.get(i).getEverything());
            if(records.get(i).getId().equals(d.get(0))) {
                records.get(i).setPaid();
                paidAmount += records.get(i).getAmount();
                records.get(i).setPaid();
                records.get(i).setPaidMonth(fin);
                System.out.println("Game Paid: "+records.get(i).getEverything());
                d.remove(0);
                if(records.size()==0) {
                    break;
                }
            }
            i++;
        }
        br.close();
        Files.delete(read);
        System.out.println("br close");
        //  Files.deleteIfExists(gamepath);
        System.gc();
        fileGame2(records);
        return paidAmount;  
    } catch (IOException e1) {
        JOptionPane.showMessageDialog(null,e1.getMessage());
        e1.printStackTrace();
    }
}
问题分析与解决方案
  1. 资源未释放的根本原因

    • 当前br.close()放在try块末尾,若前面代码抛出异常,这句代码不会执行,导致BufferedReader和底层FileReader未关闭,文件句柄被占用。
    • 依赖System.gc()回收资源不可靠,GC执行时机不确定,无法保证立即释放文件句柄。
  2. 正确的资源释放方式
    使用Java 7+支持的try-with-resources语法,它会自动关闭实现AutoCloseable接口的资源,无论代码是否抛出异常:

    // 替换原BufferedReader创建逻辑
    try (BufferedReader br = new BufferedReader(new FileReader(dabe))) {
        // 读取文件、处理数据的全部逻辑都放在这个try块内
        while ((line = br.readLine() ) != null) {
            // 原读取解析逻辑
        }
        // 后续的records处理逻辑也可放在此处
    } // 此处自动关闭br,无需手动调用close()
    
  3. 其他优化点

    • 原代码中Files.copy后立刻删除再复制的操作冗余,可直接先删除目标文件再复制,或使用StandardCopyOption.REPLACE_EXISTING参数覆盖:Files.copy(gamepath, New, StandardCopyOption.REPLACE_EXISTING)。
    • 路径字符串需注意反斜杠转义,确保路径格式正确。
    • 移除手动调用的System.gc(),确保资源正确关闭后,文件句柄会被自动释放。

内容的提问来源于stack exchange,提问作者Brandon Myers

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.09 10:20:35