如何在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(); } }
问题分析与解决方案
资源未释放的根本原因
- 当前
br.close()放在try块末尾,若前面代码抛出异常,这句代码不会执行,导致BufferedReader和底层FileReader未关闭,文件句柄被占用。 - 依赖
System.gc()回收资源不可靠,GC执行时机不确定,无法保证立即释放文件句柄。
- 当前
正确的资源释放方式
使用Java 7+支持的try-with-resources语法,它会自动关闭实现AutoCloseable接口的资源,无论代码是否抛出异常:// 替换原BufferedReader创建逻辑 try (BufferedReader br = new BufferedReader(new FileReader(dabe))) { // 读取文件、处理数据的全部逻辑都放在这个try块内 while ((line = br.readLine() ) != null) { // 原读取解析逻辑 } // 后续的records处理逻辑也可放在此处 } // 此处自动关闭br,无需手动调用close()其他优化点
- 原代码中
Files.copy后立刻删除再复制的操作冗余,可直接先删除目标文件再复制,或使用StandardCopyOption.REPLACE_EXISTING参数覆盖:Files.copy(gamepath, New, StandardCopyOption.REPLACE_EXISTING)。 - 路径字符串需注意反斜杠转义,确保路径格式正确。
- 移除手动调用的
System.gc(),确保资源正确关闭后,文件句柄会被自动释放。
- 原代码中
内容的提问来源于stack exchange,提问作者Brandon Myers
相关产品推荐
相关产品推荐

