2017-06-15 24 views
0

アンラップされた接続を持つHikariCPを使用したリソースリークに問題があります。コードを少し説明してください。アンカーされたoracle.jdbc.driver.T4CConnectionを使用したHikariCP接続のリーク

oracle.sql.BFILEのOracleメソッドにアクセスするには、ラップされていない接続を使用する必要があります。 Oracle Directoryからバイナリをストリーミングしています。

データソース例:アプリは非常に古いとTomcat-6上で実行されているよう

private static DataSource unwrapDatasource; 
public static synchronized DataSource getUnwrappedDataSource() { 
    if (unwrapDatasource == null) { 
     HikariConfig config = new HikariConfig(); 
     config.setMaximumPoolSize(50); 
     config.setLeakDetectionThreshold(120000); 
     config.setJdbcUrl(DATABASEURL); 
     config.addDataSourceProperty("user", USERNAME); 
     config.addDataSourceProperty("password", DBPASSWORD); 
     config.addDataSourceProperty("driverType", "thin"); 
     config.setDriverClassName("oracle.jdbc.pool.OracleDataSource"); 
     config.setMaxLifetime(300000); 
     config.setPoolName("UNWRAP"); 
     unwrapDatasource = new HikariDataSource(config); 
    } 

    return unwrapDatasource; 
} 

    public static Connection getUnwrappedConnection() { 
    Connection con = null; 
    try { 
     con = this.getUnwrappedDataSource().getConnection().unwrap(oracle.jdbc.driver.OracleConnection.class); 
    } catch (SQLException ex) { 
     //logger junk ommitted for brevity 
    } 
    return con; 
} 

がHikariCP-java7-2.4.12を使用しました。私が使用できるように

 Connection con = null; 
    PreparedStatement pstmt = null; 
    OracleResultSet rs = null; 
    InputStream inputStream = null; 
    StringBuilder stringBuilder = new StringBuilder(128); 
    try { 
      con = DataSourceConstants.getUnwrappedConnection(); 

      pstmt = con.prepareStatement("SELECT BFILENAME('ORACLE_DIR', 'fileDownload.12345') AS BFILE from dual"); //hardcoded for example 
      rs = (OracleResultSet) pstmt.executeQuery(); 

      rs.next(); //Assumption if rs.next() blows up, catch would grab it and resources would all attempt to close in finally block 

      bfile = rs.getBFILE(1); 
      bfile.open(); 
      inputStream = bfile.getBinaryStream(); 
      char c; 
      long size = bfile.length(); 

      int i = 0; 
      do { 
       c= (char) inputStream.read(); 
       stringBuilder.append(c); 
      } while (++i < size); 

      } catch (Exception ex) { 
       //logger ommitted but not throwing here 
      } finally { 
      //cleanup resources 
      try { inputStream.close(); } catch (Exception ex) {} 
      try { bfile.close(); } catch (Exception ex) {} 
      try { rs.close(); } catch (Exception ex) {} 
      try { pstmt.close(); } catch (Exception ex) {} 
      try {con.close(); } catch (Exception ex){} 
      } 
     //use stringBuilder later in built output. 

は、したがって、上記の開封されたT4CConnectionを取得します。 はここでここでの接続があり、それがどのように使われるか

com.zaxxer.hikari.pool.ProxyLeakTask.run(poolProxyLeak.java:91) : <Connection leak detection triggered for {}, stack trace follows> 
java.lang.Exception: Apparent connection leak detected 
    at myapp.package.obfuscated.getUnwrapConnection(DataSourceConstants.java:253) 
    at myapp.package.obfuscated.BB.execute(DatabaseCallingClass2.java:106) 
    at myapp.package.obfuscated.BB.execute(DatabaseCallingClass2.java:85) 
    at myapp.package.obfuscated.AA.execute(DataBaseCallingClass.java:52) 
    at org.apache.struts.action.RequestProcessor.processActionPerform(RequestProcessor.java:425) 
    at org.apache.struts.action.RequestProcessor.process(RequestProcessor.java:228) 
    at org.apache.struts.action.ActionServlet.process(ActionServlet.java:1913) 
    at org.apache.struts.action.ActionServlet.doPost(ActionServlet.java:462) 
    at javax.servlet.http.HttpServlet.service(HttpServlet.java:643) 
    at javax.servlet.http.HttpServlet.service(HttpServlet.java:723) 
    at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:290) 
    at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:206) 
    at org.displaytag.filter.ResponseOverrideFilter.doFilter(ResponseOverrideFilter.java:123) 
    at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:235) 
    at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:206) 
    at org.apache.catalina.core.StandardWrapperValve.invoke(StandardWrapperValve.java:233) 
    at org.apache.catalina.core.StandardContextValve.invoke(StandardContextValve.java:191) 
    at org.apache.catalina.authenticator.AuthenticatorBase.invoke(AuthenticatorBase.java:563) 
    at org.apache.catalina.core.StandardHostValve.invoke(StandardHostValve.java:127) 
    at org.apache.catalina.valves.ErrorReportValve.invoke(ErrorReportValve.java:103) 
    at org.apache.catalina.core.StandardEngineValve.invoke(StandardEngineValve.java:109) 
    at org.apache.catalina.connector.CoyoteAdapter.service(CoyoteAdapter.java:293) 
    at org.apache.coyote.http11.Http11Processor.process(Http11Processor.java:859) 
    at org.apache.coyote.http11.Http11Protocol$Http11ConnectionHandler.process(Http11Protocol.java:610) 
    at org.apache.tomcat.util.net.JIoEndpoint$Worker.run(JIoEndpoint.java:503) 
    at java.lang.Thread.run(Thread.java:745) 

にリークされたと報告されます接続のサンプルですOracleResultSetおよびBFILE/getBFILE()を使用します。 BFILEを取得するためにこの構造を使用する2つの別々のクラスがLeakingとBFILEを使用しないが、OracleCallableStatementを使用するためのUnwrapped Connectionを使用する別のメソッドの両方が漏れています。私は3つのDataSourceをインスタンス化して、すべてのコネクタをタイプ/機能別に分割しました。唯一のリークはDatasource.getConnection()。unwrap(oracle.jdbc.driver.OracleConnection.class)をコネクタに使用しているプールです。

アンラップされた接続で何か問題がありますか?これが唯一漏れているのはなぜですか?これは既知のドライバのバグですか? BFILEはあまり人気がないようです...

答えて

1

getUnwrappedConnection()でやっていることは、あなたがしなければならないことではありません。アンラッピングする場合、あなたはその接続を閉じることがプールに返すものであるため、接続プールの接続を保持する必要があります。最初にプールから接続を取得し、本当に必要な場所でのみアンラップし、完了したらデータソースから取得した元の接続を閉じます。

Do 実際の物理接続を閉じるため、接続プールを使用する目的を無効にするため、アンラップされた接続を閉じます。短い中のSO

try (Connection connection = dataSource.getConnection()) { 
    OracleConnection unwrapped = connection.unwrap(oracle.jdbc.driver.OracleConnection.class) 

    ... 

    // Do not close (or use try-with-resources) on unwrapped 
} 
+0

この答えは正しいです。 – brettw

+0

ありがとうございました!それは今意味がある。私は、プールされていないコネクションを閉じると、プールされたコネクションへの参照が解放され、少なくともGCでなければならないと考えました。今私はそれがどこにあるかを見て、パッチは方法で:) – JustinL

関連する問題