【问题标题】:Sonar way with Findbugs not detecting database connection closeFindbugs 的声纳方式未检测到数据库连接关闭
【发布时间】:2014-09-18 11:43:18
【问题描述】:

我们已经使用 Findbugs 和 PMD 的规则集设置了 SonarQube(版本 4.3.2)。

面临的问题详情如下: 有一个应用程序有一个类,它创建一个 Connection 对象 (java.sql.Connection) 并简单地将连接对象传递给 ArrayDescriptor.createDescriptor 方法。 ArrayDescriptor 类是一个内部 Oracle 类 (oracle.sql.ArrayDescriptor)。现在代码对连接对象没有做任何其他事情。 代码没有关闭为传递给会导致泄漏连接的方法而创建的连接(据我所知)。在连接关闭的地方(幸运的是!)它没有在 finally 块中完成。现在,Findbugs 的理想规则应该已经抓住了这一点。 据我了解,应该违反了以下活动规则:

  1. 不好的做法 - 方法可能无法关闭数据库资源
  2. 不好的做法 - 方法可能无法在异常时关闭数据库资源
  3. 不好的做法 - 方法可能无法关闭流
  4. 不好的做法 - 方法可能无法在异常时关闭流

但是这些代码都没有报告。

然后我们安装了 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 保留为类级别变量不是一个好习惯,我们正在尝试教育不要使用它,但是对于这样做的人,理想情况下应该检测到连接的关闭)

因此我的问题是: 1. 我的期望是上述所有规则都应该在 a.创建连接对象但未关闭或创建连接对象并将其传递给内部方法 (ArrayDescriptor.createDescriptor) c) 在 finally 块中创建、关闭但未关闭连接。 这种期望是错误的吗? 2. 如果预期是正确的,为什么 Sonar 和 Findbugs 没有检测到它? 3. 为什么 PMD 只检测方法级别的变量还是有其他问题。

感谢您对此的帮助。

SonarQube 版本 - 4.3.2

信息: 插件版本 Checkmarx - 7.1.2-3.0.1 查找错误 - 2.1 雅可可 - 2.1 爪哇 - 2.1 用于 Java 的 Squid - 2.1 万能 - 2.1 网络 - 2.1

【问题讨论】:

    标签: java sonarqube findbugs pmd


    【解决方案1】:

    我不确定它是否对您有帮助,但我们不得不进行计划外的代码重构以避免第一条规则:

    在这种情况下,使用 .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
    

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 2011-12-29
      • 1970-01-01
      • 2012-04-23
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多