【发布时间】:2013-02-21 13:54:51
【问题描述】:
当我在此方法中的 try 块内的两个 return 值中遇到资源泄漏警告时,我在 Eclipse 中正常工作:
@Override
public boolean isValid(File file) throws IOException
{
BufferedReader reader = null;
try
{
reader = new BufferedReader(new FileReader(file));
String line;
while((line = reader.readLine()) != null)
{
line = line.trim();
if(line.isEmpty())
continue;
if(line.startsWith("#") == false)
return false;
if(line.startsWith("#MLProperties"))
return true;
}
}
finally
{
try{reader.close();}catch(Exception e){}
}
return false;
}
我不明白这将如何导致资源泄漏,因为我在try 范围之外声明了reader 变量,在try 块内添加了一个资源并在finally 块中使用另一个try...catch 忽略异常和一个NullPointerException 如果reader 是null 出于某种原因...
据我所知,finally 块总是在离开try...catch 结构时执行,因此在try 块内返回一个值仍然会在退出方法之前执行finally 块...
这很容易证明:
public static String test()
{
String x = "a";
try
{
x = "b";
System.out.println("try block");
return x;
}
finally
{
System.out.println("finally block");
}
}
public static void main(String[] args)
{
System.out.println("calling test()");
String ret = test();
System.out.println("test() returned "+ret);
}
结果:
calling test()
try block
finally block
test() returned b
知道了这一切,如果我在 finally 块中关闭它,为什么 eclipse 会告诉我 Resource leak: 'reader' is not closed at this location?
回答
我只想在this answer 中添加他是正确的,如果new BufferedReader 抛出异常,FileReader 的实例将在被垃圾收集器销毁时打开,因为它不会分配给任何变量并且@ 987654343@ 块不会关闭它,因为 reader 将是 null。
这就是我修复这个可能的泄漏的方法:
@Override
public boolean isValid(File file) throws IOException
{
FileReader fileReader = null;
BufferedReader reader = null;
try
{
fileReader = new FileReader(file);
reader = new BufferedReader(fileReader);
String line;
while((line = reader.readLine()) != null)
{
line = line.trim();
if(line.isEmpty())
continue;
if(line.startsWith("#") == false)
return false;
if(line.startsWith("#MLProperties"))
return true;
}
}
finally
{
try{reader.close();}catch(Exception e){}
try{fileReader.close();}catch(Exception ee){}
}
return false;
}
【问题讨论】:
-
旁注:
if(line.startsWith("#") == false)一般写成:if(!line.startsWith("#"))。 -
警告看起来完全是假的。
-
在 finally 子句中,你必须检查 reader 是否不为空,因为如果由于某种原因 reader 变量没有被实例化,你将有一个 NPE。
-
移动新的 BufferedReader(new FileReader(file));到 bufferedreader 的初始化,如果它是 null 它不会尝试关闭
-
只是一个想法,但也许是因为你的例外。如果读取时出现 IOError,则永远不会捕获此异常,并且您的流永远不会关闭。
标签: java eclipse resources eclipse-juno java-6