Java 资源泄漏:';在';永远不会关闭,尽管它已关闭

Java 资源泄漏:';在';永远不会关闭,尽管它已关闭,java,java-io,Java,Java Io,我知道有几个标题类似的问题,但大多数问题只是忘记在他们的流中添加close()指令。这是不同的 假设我有以下最简单的例子: public void test() throws IOException { InputStream in; if( file.exists() ) { in = new FileInputStream( file ); } else { in = new URL( "some url" ).

我知道有几个标题类似的问题,但大多数问题只是忘记在他们的流中添加
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)中的“in”永远不会关闭。
但是当我将
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();
    }
}

这是怎么回事?

我怀疑警告不正确。它可能检查您是否正在关闭同一范围内的流。在第二种情况下,您没有关闭第二个流。

由于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,它看到输入流“in”,可能会通过所有的障碍和障碍,到达您将要使用它的点。不幸的是,正如有人指出的,举例来说,您的代码有点不可靠。按照我的详细说明以及@duffymo执行此操作,您将消除警告。

如果文件不存在,并且您尝试关闭一个不存在的文件,则您的输入流可能无法初始化


您的第二个示例还需要一个封闭的语句来避免泄漏。

以下是我的编写方法:

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();
    }
}

当您在打开资源后显式抛出异常时,也会发生相同的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方法的习惯,以确保资源被正确、一致地关闭。

我有如下方法:

InputStream content = httpResponse.getEntity()==null?null:httpResponse.getEntity().getContent();
这也给了我们同样的温暖。但如果我就这样离开它:

InputStream content =httpResponse.getEntity().getContent();
我没有收到任何警告。这不奇怪吗


--我希望我的信息是增加知识的原始问题。谢谢

警告哪里。石斑鱼类?Java编译?哪个IDE?哪个版本?“…警告消失:”。哪些警告?您应该尝试/最终阻止。在finally块中关闭流,以确保在抛出异常时不会错过。哎呀,意外删除了一段。编辑原始帖子以修复它。警告是
资源泄漏:“in”永远不会关闭
@duffymo如果构造函数引发异常,那么我就没有可以关闭的流!那么它是空的。谢谢,这确实有效。然而,我仍然不明白,
in!=null
并且
FileInputStream
构造函数引发异常。假设
FileInputStream
构造函数抛出异常。这意味着
中的
仍然为空。因此,
is.close()
语句无论哪种方式都会被忽略?我更喜欢向上投票并接受您的感谢。您的示例是人为设计的,因为您除了调用构造函数之外什么都不做。但是如果您实际使用的是InputStream,那么如果读取失败,它可能会引发异常。没有什么是“被忽视的”。这不是程序的工作方式。从Java 7开始,您可以使用try with resources。这是一个错误的答案,因为如果没有什么可以做的,那么它不应该抛出资源警告,这是编译器“抛出资源警告”中的一个错误?你在说什么?close方法抛出一个选中的异常——您别无选择,只能处理它。你为什么不把你的答案贴出来,让我们看看你要说什么?这个问题已经问了将近8年了。你能做的就是找到旧答案并发表恶作剧般的评论来提升你的声誉吗?谢谢,这很有效。然而,我对这个解决方案有一个理解上的问题。这和这里的答案是一样的:你能解释一下吗?我同意这个答案,我投了无意义和无法解释的否决票。这个警告显然是错误的。第二个例子证明了这一点,那就是真的缺少了一个结束。如果无法初始化“in”,则会引发异常,并且无法到达in.close()。此代码不可能“尝试关闭不存在的文件”。