我们已经使用Findbugs和PMD的Ruleset设置了SonarQube(版本4.3.2)。
所面临的问题详情如下: 有一个应用程序有一个创建Connection对象的类(java.sql.Connection),只是简单地传递连接对象到ArrayDescriptor.createDescriptor方法。 ArrayDescriptor类是内部Oracle类(oracle.sql.ArrayDescriptor)。现在代码对连接对象没有做任何其他事情。 代码没有关闭为传递给方法而创建的连接,这会导致泄漏连接(据我所知)。在连接关闭的地方(幸运的是!),它不是在finally块中完成的。现在理想情况下,Findbugs的规则本应该抓住这一点。 根据我的理解,应该违反以下有效规则:
但是这些代码都没有报告。
然后我们安装了PMD插件以包含规则 - Repository:pmd Key:CloseResource
启用此功能时,会报告closeResource,但仅限于连接对象是方法级别变量的位置,例如:
public void nameOfMethod() throws SQLException {
try {
InitialContext context = new InitialContext();
DataSource ds = (DataSource) context.lookup("DS");
Connection connnew = ds.getConnection();
}
但是,如果Connection对象是类级别变量,则即使此规则也不会检测到该问题。 (我知道将Connection保持为类级别变量并不是一个好习惯,我们正在努力教育不使用它,但对于那些这样做的人来说,理想情况下应该检测到连接的关闭)
因此我的问题是: 我的期望是上述所有规则都应该在一个地方检测到。创建并未关闭Conenction对象或创建Connection对象并将其传递给内部方法(ArrayDescriptor.createDescriptor)c)在finally块中创建,关闭但未关闭的连接。 这种期望是错的吗? 2.如果期望是对的,为什么Sonar与Findbugs没有检测到它? 3.为什么PMD只检测方法级别变量或存在其他问题。
感谢你的帮助。
SonarQube版本 - 4.3.2
的信息: 插件版本 Checkmarx - 7.1.2-3.0.1 Findbugs - 2.1 JaCoCo - 2.1 Java - 2.1 Squid的Java - 2.1 Surefire - 2.1 网络 - 2.1
答案 0 :(得分:0)
我不确定它是否对您有所帮助,但我们必须制作一个计划外的代码重构来避免第一条规则:
在这种情况下使用.isClosed()方法抛出和异常,如果它的情况永远不会达到.close()语句,导致:错误的做法 - 方法可能无法关闭数据库资源
public class ConexionBD {
// JDBC driver name and database URL
static final String JDBC_DRIVER = "com.mysql.jdbc.Driver";
static final String DB_URL = "jdbc:mysql://localhost:3306/regactividades";
@Value("${jdbc.username}")
private String user;
@Value("${jdbc.password}")
private String pass;
public void ejecuta(String[] args) {
Connection conn = null;
Statement stmt = null;
ResultSet rs = null;
try{
Class.forName("com.mysql.jdbc.Driver");
conn = DriverManager.getConnection(DB_URL,user,pass);
stmt = conn.createStatement();
String sql;
sql = "SELECT * FROM table";
rs = stmt.executeQuery(sql);
while(rs.next()){
int id = rs.getInt("id");
String des = rs.getString("description");
System.out.print("ID: " + id);
System.out.print(", des: " +des);
}
// stmt.close(); this code gone...
//rs.close();
//conn.close();
}catch(SQLException se){
se.printStackTrace();
} catch (ClassNotFoundException e) {
e.printStackTrace();
}finally{
try{
if(stmt!=null){
// if (!stmt.isClosed()){
stmt.close();}
// }
}catch(Exception se2){
}// nothing we can do
try{
if(rs!=null){
//if (!rs.isClosed()){
rs.close();}
// }
}catch(Exception se){
}
try{
if(conn!=null){
// if (!conn.isClosed()){
conn.close();}
// }
}catch(Exception se){
}
}//end try
System.out.println("bye!");
}//end main
}//end FirstExample