问题
I want to have a clean project. So I used Sonar to detect potential defects, ...
On the below method, Sonar asks to : 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;
}
Can you explain me what I did wrong and how to do to avoid Sonar message? Thank you.
回答1:
Connection
implements AutoCloseable
which Sonar is detecting (it doesn't care whether you're using a connection or some other auto closeable thingy).
Not closing such a resource could lead to a resource leak so Sonar wants you to do something like this:
//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();
}
The problem in your case is that you're just creating the connection and then return it - and I strongly suspect you want to keep it open :)
Sonar can't be sure that you'll ever close the connection so it will complain. There might be ways to make Sonar ignore things like this (I don't use it that much so I'm not too familiar with the options here) but it's still a potential risk that you'd have to mitigate somehow.
回答2:
The code you have above has the potential to leave the Connection
object open, which can cause significant issues.
You can guarantee that the Connection
is closed when you are finished with it in a few ways:
public Connection createConnection() {
return connectionFactory.createConnection(...); // note that this method does not open the connection
}
Then, when you want to use the connection, either use try-catch-finally:
try {
Connection c = createConnection();
doSomethingWithPossibleException(c);
} catch(PossibleException e) {
handleException(e);
} finally {
// now close the connection
c.close();
}
or you can use try-with-resources (from Java 7 onwards):
try (Connection c = getConnection()) {
doSomethingWithPossibleException(c);
} catch (PossibleException e) {
handle(e);
}
IMO try-with-resources is a little more readable, although tastes differ on this matter. Note, the object you create in the try-with-resources must implement the AutoCloseable
interface.
回答3:
In java if you are using resource like FileInptStream, Connection, ResultSet, Input/OutputStream, BufferedReader, PrintWriter
you have to close it before garbage collection happens.
so basically whenever connection object no longer in use you have to close it.
try below snippet
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
}
In the try with resource case connection will automatically close by jvm, but Connection interface must be extends with AutoCloseable / Closable
interface.
回答4:
I find out one solution to resolve this issue. you can override the existing DBManger like this:
@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();
}
}
来源:https://stackoverflow.com/questions/59945517/sonar-asks-to-use-try-with-resources-or-close-this-connection-in-a-finally