Sonar要求“使用try-with-resources或在“ finally”子句中关闭此“ Connection”。

时间:2020-01-28 09:21:04

标签: java sonarqube

我想要一个干净的项目。所以我用Sonar来检测潜在的缺陷,...

在以下方法中,Sonar要求:Use try-with-resources or close this "Connection" in a "finally" clause.

private Connection createConnection() throws JMSException {
    MQConnectionFactory mqCF = new MQConnectionFactory();
    ...

    Connection connection = mqCF.createConnection(...);
    connection.start();

    return connection;
}

您能解释一下我做错了什么以及如何避免Sonar消息吗?谢谢。

4 个答案:

答案 0 :(得分:2)

Connection实现了Sonar正在检测的AutoCloseable(它不在乎您是在使用连接还是其他一些自动关闭的东西)。

不关闭此类资源可能会导致资源泄漏,因此Sonar希望您执行以下操作:

//try-with-resources - the connection will be closed after this block
try(Connection connection = mqCF.createConnection(...)) {
  //use connection here
}

//traditional try - the connection will be closed after the finally block
Connection connection = mqCF.createConnection(...);
try {
  //use connection here
} finally {
   connection.close();
}

您所遇到的问题是您只是创建连接然后返回它-我强烈怀疑您想保持其打开状态:)

Sonar不能确定您是否会关闭连接,否则它将抱怨。也许有一些方法可以使Sonar忽略这样的事情(我没有太多使用它,所以我对这里的选项不太熟悉),但是仍然有潜在的风险,您必须以某种方式减轻它。

答案 1 :(得分:1)

您上面的代码有可能使Connection对象保持打开状态,这可能会导致严重的问题。

完成Connection的几种方法后,可以保证它已关闭:

public Connection createConnection() {
    return connectionFactory.createConnection(...);  // note that this method does not open the connection
}

然后,当您要使用连接时,请使用 try-catch-finally

try {
    Connection c = createConnection();
    doSomethingWithPossibleException(c);
} catch(PossibleException e) {
    handleException(e);
} finally {
    // now close the connection
    c.close();
}

或者您可以使用 try-with-resources (从Java 7开始):

try (Connection c = getConnection()) {
    doSomethingWithPossibleException(c);
} catch (PossibleException e) {
    handle(e);
}

IMO的try-with-resources更具可读性,尽管在此问题上口味有所不同。请注意,您在try-with-resources中创建的对象必须必须实现AutoCloseable接口。

答案 2 :(得分:1)

在Java中,如果您正在使用FileInptStream, Connection, ResultSet, Input/OutputStream, BufferedReader, PrintWriter之类的资源,则必须在垃圾回收发生之前将其关闭。 因此基本上,每当不再使用连接对象时,您都必须关闭它。

尝试以下代码段

Connection c = null;
    try {
        c = mqCF.createConnection(...);
        // do something
    } catch(SomeException e) {
        // log exception
    } finally {
        if(c != null)
           c.close();
    }

//try-with-resources
try(Connection connection = mqCF.createConnection(...)) {
  //use connection here
}

在尝试使用资源的情况下,jvm将自动关闭连接,但是必须使用AutoCloseable / Closable接口扩展Connection接口。

答案 3 :(得分:0)

我找到了一种解决此问题的方法。 您可以像这样覆盖现有的DBManger:

@Override
    public Connection getConnection() throws SQLException {
        Connection conn = new ProxyConnection(DriverManager.getConnection(...));
        return conn;
    }

    private static class ProxyConnection implements Connection {

        Connection connection;

        private ProxyConnection(Connection connection) {
            this.connection = connection;
        }

        /**
         * Standard method, add logging.
         */
        @Override
        public void close() throws SQLException {
            logger.debug("Connection to database was released");
            connection.close();
        }
    }