为什么编译器警告资源泄漏?

时间:2014-06-27 10:30:43

标签: java eclipse compiler-warnings resource-leak

我无法理解为什么编译器会在以下代码中警告我资源泄漏(Resource leak: 'conn' is not closed at this location):

    Connection conn = null;
    try {
        conn = DatabaseConnectionPool.getConnectionFromPool();
        // Some code
        try {
            // Other code
        } catch (final SomeException e) {
            // More code
            throw e; // Resource leak: 'conn' is not closed at this location
        }

    } catch (final SQLException | OtherExceptions e) {
        // Some more code
    } finally {
        try {
            // Another bunch of code
        } finally {
            DatabaseConnectionPool.freeConnection(conn);
        }
    }

请注意,如果我这样写

    Connection conn = null;
    try {
        conn = DatabaseConnectionPool.getConnectionFromPool();
        // Some code
        try {
            // Other code
        } catch (final SomeException e) {
            // More code
            throw e;
        } finally {
            DatabaseConnectionPool.freeConnection(conn);
        }

    } catch (final SQLException | OtherExceptions e) {
        // Some more code
    } finally {
        // Another bunch of code
    }

警告消失了。

1 个答案:

答案 0 :(得分:3)

编译器非常容易转储。它可能无法知道DatabaseConnectionPool.freeConnection(conn)会在close上调用conn。我不确定为什么第二个例子没有触发这个警告,但可能这个功能并不完全完善,可能会产生漏报。基本上,任何资源都应该通过直接在获取资源的地方调用close方法来关闭;这是编译器可以确定要关闭它的唯一方法,它不是程序间分析来检查被调用函数是否调用close

使用java7,您应该考虑使用try-with-resource语句;它是 鼓励处理任何资源的方式,即:

try(Connection conn = ...){
   // Do something with conn

   // No close necessary here, done implicitly by the try statement
}

通过调用close以外的方法来关闭连接的整个模式对我来说似乎有缺陷(它有效,但我强烈反对它的用法):任何资源都应该能够通过调用{{}来关闭它自己1}}。如果您的资源需要调用close来关闭它,那么您违反了Java的资源合同。如果您使用try-with-resource语句,则无论如何都无法选择:语句将调用DatabaseConnectionPool.freeConnection而不是您的方法。