我想要一个干净的项目。所以我用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消息吗?谢谢。
答案 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();
}
}