我知道有几个类似的有问题的问题,但大多数人只是忘记在他们的流上加上close()
指令。这是不同的。
假设我有以下最小的例子:
public void test() throws IOException
{
InputStream in;
if( file.exists() )
{
in = new FileInputStream( file );
}
else
{
in = new URL( "some url" ).openStream();
}
in.close();
}
这在Eclipse(Juno SR1)中给出了Resource leak: 'in' is never closed
警告。
但是当我将in.close()
移动到条件块中时,警告就会消失:
public void test() throws IOException
{
InputStream in;
if( file.exists() )
{
in = new GZIPInputStream( new FileInputStream( file ) );
in.close();
}
else
{
in = new URL( "some URL" ).openStream();
}
}
这里发生了什么?
答案 0 :(得分:6)
由于IO异常,您可能会遇到资源泄漏(可能)
尝试执行以下操作:
public void test() throws IOException
{
InputStream in= null;
try {
if( file.exists() )
{
// In this case, if the FileInputStream call does not
// throw a FileNotFoundException (descendant of IOException)
// it will create the input stream which you are wrapping
// in a GZIPInputStream (no IO exception on construction)
in = new GZIPInputStream( new FileInputStream( file ) );
}
else
{
// Here however, if you are able to create the URL
// object, "some url" is a valid URL, when you call
// openStream() you have the potential of creating
// the input stream. new URL(String spec) will throw
// a MalformedURLException which is also a descendant of
// IOException.
in = new URL( "some url" ).openStream();
}
// Do work on the 'in' here
} finally {
if( null != in ) {
try
{
in.close();
} catch(IOException ex) {
// log or fail if you like
}
}
}
}
执行上述操作将确保您已关闭该流,或至少尽最大努力这样做。
在原始代码中,您已声明了InputStream但从未初始化。这是一个糟糕的形式开始。如上所示,将其初始化为null。我的感觉,而且我现在没有运行Juno,就是它看到InputStream'in',可能会通过所有的箍和障碍来达到你将要使用它的程度。不幸的是,正如有人指出的那样,你的代码对于一个例子来说有点狡猾。按照我和@duffymo的详细说明这样做,你将摆脱警告。
答案 1 :(得分:5)
以下是我写的方式:
public void test() throws IOException
{
InputStream in = null;
try {
if(file.exists()) {
in = new FileInputStream( file );
} else {
in = new URL( "some url" ).openStream();
}
// Do something useful with the stream.
} finally {
close(in);
}
}
public static void close(InputStream is) {
try {
if (is != null) {
is.close();
}
} catch (IOException e) {
e.printStackTrace();
}
}
答案 2 :(得分:4)
我怀疑警告不正确。它可能会检查您是否在同一范围内关闭流。在第二种情况下,您没有关闭第二个流。
答案 3 :(得分:0)
如果文件不存在并且您尝试关闭不存在的文件,则可能无法初始化您的输入。
你的第二个例子也需要一个密切的声明来避免泄密。
答案 4 :(得分:0)
当您在打开资源后显式抛出异常时,可能会发生同样的Eclipse报告:
public void method() throws IOException {
BufferedReader br = new BufferedReader(new FileReader("myfile.txt"));
while (br.ready()) {
String line = br.readLine():
if (line.length() > 255) {
throw new IOException("I am some random IOException");
}
}
br.close();
}
这是一些用于演示目的的人为代码,所以不要太费劲。
如果要对该线路进行评论,警告就会消失。当然,您需要确保正确关闭该资源。你可以这样做:
if (line.length() > 255) {
br.close();
throw new IOException("I am some random IOException");
}
虽然在这种情况下不要依赖Eclipse警告。养成使用try / finally方法的习惯,确保资源正确且一致地被关闭。
答案 5 :(得分:0)
我有类似的东西:
InputStream content = httpResponse.getEntity()==null?null:httpResponse.getEntity().getContent();
给出相同的warrning。但如果我这样离开它:
InputStream content =httpResponse.getEntity().getContent();
我没有收到任何补偿。不奇怪还是什么?
- 我希望我的信息能够为原始问题添加知识。谢谢!