2

最終的にブロックがリソースを閉じるのに本当に信頼できるかどうか疑問に思いました。データベース接続など?

私たちのアーキテクトによると、特にWebアプリケーションのシナリオでは、最終的にブロックはデータベース接続を閉じるのに信頼性がありません。

理論によれば、最終的にブロックは、コードの実行ステータスに関係なく、ロジックフローの最後で実行する必要があります。最後に、ブロックがベストプラクティスです。

JDK-1.4、プレーンSQLクエリを使用し、接続プールからデータベース接続を取得するWebアプリケーションプロジェクトに取り組んでいます。ほとんどのSQLステートメントはネストされたステートメントであり、単一のメソッドには複数のStatementオブジェクトとResultSetオブジェクトが含まれています。

このシナリオでは、finallyブロックについて懐疑的です。テストによると、finallyブロックはリソースを解放せず、代わりにWebアプリがより多くの接続を取得しているためです。最後に、Tomcat5.5は2/3時間ごとにハングします。

次に、finallyブロックを削除し、SQL操作を実行した直後とcatchブロックでリソースを解放しました。その後、Webアプリはリソースを完全にリリースし、Tomcatはもうハングしていません。

したがって、私は最終的にブロックする理論について本当に混乱しています。

これがコードスニペットです。コーディング手法が間違っているかどうかアドバイスしてください。

        ... .. . . .. . .. . . .. .. . 
    ........ . .. . . ... . .. . .

    Connection dbCon = null;
    Statement stmt1 = null;
    ResultSet rs1 = null;

    try {
        dbCon = DB.getConnection();

        stmt1 = dbCon.createStatement();            
        rs1  = stmt1.executeQuery("sql Query as String");

        while(rs1.next()){

            String col1 = rs1.getString("DB_COL_1");
            int col2 = rs1.getInt("DB_COL_2");
            String col3 = rs1.getString("DB_COL_3");

            if(col3 != null){   

                Statement stmt2 = null;
                ResultSet rs2 = null;

                try{
                    stmt2 = dbCon.createStatement();                                                        
                    rs2 = stmt2.executeQuery("sql Query as String");

                    ------- - ----

                    while(rs2.next()){
                        String col4 = rsTierMember.getString("DB_COL_4");

                        ... . .. . . . .....                                
                        . .. . .. . . . . . ..          
                    }

                    ... . .. .. ... .

                }catch(SQLException sqlExp){

                } catch (Exception e) { 

                }finally{
                    try{
                        if(rs2!=null)
                            rs2.close();
                        if(stmt2!=null)
                            stmt2.close();
                    }catch(Exception ex){}                                                                 
                }
            }

        }

         .... . .. .

    }catch (SQLException e) {

    } catch (Exception e) {     

    }finally{
        try{            
            if(rs1!=null)
                rs1.close();
            if(stmt1!=null)
                stmt1.close();
            if(dbCon!=null) 
                dbCon.close;                
        }catch(Exception ex){

        }
    }


    ...... . . . . . ...
    ... . .. . .. . . .. .
4

3 に答える 3

12

最終的にブロックがリソースを閉じるのに本当に信頼できるかどうか疑問に思いました。データベース接続など?

それはあなたが「信頼できる」とはどういう意味かによります。

  • JVMがハードに中止された場合(JITのバグなどが原因)、実行されない場合があります。
  • JVMが正常に終了している場合は、実行されない可能性があります(Harmeetの回答を参照)。
  • tryブロックの内容が永久にハングすることは実行されません
  • コンピュータの電源が突然切れた場合は実行されません

これらすべての場合において、データベースは接続のもう一方の端がとにかくなくなったことに気付くと思います。

アーキテクトがブロックが実行されないと信じている特定のfinallyシナリオを念頭に置いている場合、アーキテクトはそのシナリオの例を提供する必要があります。その時点で、ほぼ確実にそれらが間違っていることを証明できます。彼らが詳細を与えることを拒否した場合は、それらを無視し、経営陣に、より権威のない建築家を探し始めるように提案します。

このシナリオでは、finallyブロックについて懐疑的です。テストによると、finallyブロックはリソースを解放せず、代わりにWebアプリがより多くの接続を取得しているためです。最後に、Tomcat5.5は2/3時間ごとにハングします。

テストが無効であるか、他の場所で接続がリークしているか、接続を閉じていないようです。ただし、検証は簡単です。ログをfinallyブロックに入れて、リソースを解放する予定のコードが少なくとも呼び出されていることを検証します。呼び出されているが接続を解放していない場合は、finallyブロックに関する問題ではなくなります。

于 2012-08-22T16:21:06.673 に答える
2

すでに投稿されている優れた回答に加えて、最後のブロックは少し間違っています

  try{            
        if(rs1!=null)
            rs1.close();
        if(stmt1!=null)
            stmt1.close();
        if(dbCon!=null) 
            dbCon.close;                
    }catch(Exception ex){

    }

rs1.close例外をスローする とどうなりますか?閉じていませんstmt1dbCon

少しかさばりますが、「通常の」状態でリソースを閉じるための最良のチャンスが保証されます(他の投稿で言及されているすべてのことを考慮しているわけではありません)

try {      
    rs1.close();
} catch (Exception exp) {}
try {      
    stmt1.close();
} catch (Exception exp) {}
try {      
    dbCon.close;                
}catch(Exception ex){}

nullそうではありません。try/catchが使用を処理するため、をチェックする必要はありません。rs1.closeまた、失敗しても気にせず、他のリソースを閉じるために最善を尽くすことができることも意味します。

万が一の場合に備えて、少なくともこれらの例外をログに記録することをお勧めします。

于 2012-08-22T20:24:37.463 に答える
2

finallyが実行されない1つのケースを次に示します。

public class FinallyDemo {    
    public static void main(String[] args) {
        try {
            System.exit(0);
        } catch (Exception ex) {
            System.out.println(ex);
        } finally {
            System.out.println("finally");
        }
    }
}

注:tryまたはcatchコードの実行中にJVMが終了すると、finallyブロックが実行されない場合があります。同様に、tryまたはcatchコードを実行しているスレッドが中断または強制終了された場合、アプリケーション全体が継続していても、finallyブロックが実行されない可能性があります。(参照)

そして、Jon Skeetについて考えてみましょう。シナリオによって異なりますが、「信頼できる」とはどういう意味ですか。

于 2012-08-22T16:26:01.697 に答える