简体   繁体   English

使用解包的oracle.jdbc.driver.T4CConnection的HikariCP连接泄漏

[英]HikariCP Connection Leak using unwrapped oracle.jdbc.driver.T4CConnection

I am having an issue with a resource leak using HikariCP with an Unwrapped Connection. 我在使用带未连接的HikariCP时发生资源泄漏问题。 A little explanation then the code. 稍微解释一下代码。

I must use an unwrapped connection to access Oracle methods for oracle.sql.BFILE. 我必须使用未包装的连接来访问oracle.sql.BFILE的Oracle方法。 This is streaming a binary out of an Oracle Directory. 这会将二进制文件从Oracle目录中流式传输出来。

DataSource Example: 数据源示例:

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;
}

Using HikariCP-java7-2.4.12 as the app is very old and running on tomcat-6. 使用HikariCP-java7-2.4.12作为该应用程序非常老,并且在tomcat-6上运行。 Here is sample of the Connection that gets reported as Leaked with 这是被报告为泄漏的连接示例

    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)

Here is the Connection and how it is used: 这是连接及其使用方式:

     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.

So The above retrieves an unwrapped T4CConnection so that I can use the OracleResultSet and BFILE / getBFILE(). 因此,上面检索了一个未包装的T4CConnection,以便我可以使用OracleResultSet和BFILE / getBFILE()。 This works and I get the result that I want, however two separate Classes using this structure to retrieve a BFILE are both Leaking, and another method that doesn't use BFILE but is using an Unwrapped Connection to use OracleCallableStatement is also leaking. 这行得通,我得到了想要的结果,但是使用此结构检索BFILE的两个单独的类都在泄漏,并且不使用BFILE但使用未包装的连接来使用OracleCallableStatement的另一种方法也在泄漏。 I have instantiated 3 DataSources to split all of the connectors by type/function, the only pool that Leaks is the one using Datasource.getConnection().unwrap(oracle.jdbc.driver.OracleConnection.class) for its connectors. 我已实例化了3个DataSource,以按类型/功能拆分所有连接器,Leaks的唯一池是使用Datasource.getConnection()。unwrap(oracle.jdbc.driver.OracleConnection.class)作为其连接器的池。

Am I doing something wrong with an unwrapped connection? 展开的连接是否存在问题? Why is this the only one that leaks? 为什么这是唯一泄漏的? Is this a known driver bug? 这是已知的驱动程序错误吗? (I haven't come up with any articles on it) BFILE doesn't seem to be very popular... (我还没有写任何文章)BFILE似乎不太受欢迎...

What you are doing in getUnwrappedConnection() is not what you should be doing: if you are unwrapping, then you need to make sure you also hold on to the connection pool connection, as closing that connection is what returns it to the pool. 您在getUnwrappedConnection()中所做的不是您应该做的:如果要展开,则需要确保还保持连接池连接,因为关闭该连接会将其返回到池中。 So first get the connection from the pool, and only unwrap at the point you really need it, and then, when you are done, close the original connection you obtained from the data source. 因此,首先从池中获得连接,然后仅在真正需要的时候解开连接,然后在完成后关闭从数据源获得的原始连接。

Do not close the unwrapped connection, because that will close the actual physical connection, and that will defeat the purpose of using a connection pool. 不要关闭展开连接,因为这将关闭实际的物理连接,这将破坏使用连接池的目的。

So in short: 简而言之:

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

    ...

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

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

相关问题 java.io.NotSerializableException-oracle.jdbc.driver.T4CConnection - java.io.NotSerializableException - oracle.jdbc.driver.T4CConnection 在oracle.jdbc.driver.T4CConnection上找到锁定的对象 - Locked object found on oracle.jdbc.driver.T4CConnection java.lang.ClassCastException:oracle.jdbc.driver.T4CConnection无法转换为com.arjuna.ats.internal.arjuna.recovery.Connection - java.lang.ClassCastException: oracle.jdbc.driver.T4CConnection cannot be cast to com.arjuna.ats.internal.arjuna.recovery.Connection oracle.jdbc.driver.T4CConnection.getSchema()异常 - oracle.jdbc.driver.T4CConnection.getSchema() exception Oracle 驱动程序错误 oracle.jdbc.driver.T4CConnection.isValid(I)Z - Oracle Driver Error oracle.jdbc.driver.T4CConnection.isValid(I)Z 无法将JAVA / Oracle-weblogic.jdbc.wrapper.poolconnection_oracle_jdbc_driver_t4cconnection强制转换为oracle.jdbc.driver.oracleconnection - JAVA/Oracle-weblogic.jdbc.wrapper.poolconnection_oracle_jdbc_driver_t4cconnection cannot be cast to oracle.jdbc.driver.oracleconnection 表类型的调用过程。 创建结构时发生异常:java.lang.AbstractMethodError:oracle.jdbc.driver.T4CConnection.createStruct - Call procedure with a table type. Exception while create Struct: java.lang.AbstractMethodError: oracle.jdbc.driver.T4CConnection.createStruct Maven编译和运行时错误java.lang.AbstractMethodError:Tomcat 8 Server上的oracle.jdbc.driver.T4CConnection.isValid(I)Z - Maven compilation and run time error java.lang.AbstractMethodError: oracle.jdbc.driver.T4CConnection.isValid(I)Z on Tomcat 8 Server 使用JDBC驱动程序在Android应用程序与Oracle DB之间建立连接 - Establishing connection between Android app and Oracle DB using JDBC driver yaml 中的 HikariCP 连接泄漏检测 - HikariCP connection leak detection in yaml
 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM