使用Findbugs的声纳方式未检测到数据库连接关闭

时间:2014-09-18 11:43:18

标签: java sonarqube findbugs pmd

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

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

  1. 不良做法 - 方法可能无法关闭数据库资源
  2. 不良做法 - 方法可能无法在异常
  3. 上关闭数据库资源
  4. 不良做法 - 方法可能无法关闭流
  5. 不良做法 - 方法可能无法在异常
  6. 上关闭流

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

    然后我们安装了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

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