com.mchange.v2.c3p0.impl.NewPooledConnection@be1839d closed by a client的正确解答

关于c3p0在debug模式下控制台抛出的如下异常:

java.lang.Exception: DEBUG -- CLOSE BY CLIENT STACK TRACE
at com.mchange.v2.c3p0.impl.NewPooledConnection.close(NewPooledConnection.java:566)
at com.mchange.v2.c3p0.impl.NewPooledConnection.close(NewPooledConnection.java:234)
at com.mchange.v2.c3p0.impl.C3P0PooledConnectionPool$1PooledConnectionResourcePoolManager.destroyResource(C3P0PooledConnectionPool.java:470)
at com.mchange.v2.resourcepool.BasicResourcePool$1DestroyResourceTask.run(BasicResourcePool.java:964)
at com.mchange.v2.async.ThreadPoolAsynchronousRunner$PoolThread.run(ThreadPoolAsynchronousRunner.java:547)

或者:

java.lang.Exception: DEBUG -- CLOSE BY CLIENT STACK TRACE
at com.mchange.v2.c3p0.impl.NewPooledConnection.close(NewPooledConnection.java:566)
at com.mchange.v2.c3p0.impl.NewPooledConnection.close(NewPooledConnection.java:234)
at com.mchange.v2.c3p0.impl.C3P0PooledConnectionPoolManager.initializeAutomaticTestTable(C3P0PooledConnectionPoolManager.java:834)
at com.mchange.v2.c3p0.impl.C3P0PooledConnectionPoolManager.createPooledConnectionPool(C3P0PooledConnectionPoolManager.java:696)
at com.mchange.v2.c3p0.impl.C3P0PooledConnectionPoolManager.getPool(C3P0PooledConnectionPoolManager.java:257)
at com.mchange.v2.c3p0.impl.C3P0PooledConnectionPoolManager.getPool(C3P0PooledConnectionPoolManager.java:271)
at com.mchange.v2.c3p0.impl.AbstractPoolBackedDataSource.getNumThreadsAwaitingCheckoutDefaultUser(AbstractPoolBackedDataSource.java:203)
at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62)
at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
at java.lang.reflect.Method.invoke(Method.java:497)
at com.mchange.v2.beans.BeansUtils.extractAccessiblePropertiesToMap(BeansUtils.java:359)
at com.mchange.v2.beans.BeansUtils.appendPropNamesAndValues(BeansUtils.java:324)
at com.mchange.v2.c3p0.ComboPooledDataSource.toString(ComboPooledDataSource.java:539)
at com.mchange.v2.c3p0.impl.AbstractPoolBackedDataSource.getPoolManager(AbstractPoolBackedDataSource.java:462)
at com.mchange.v2.c3p0.impl.AbstractPoolBackedDataSource.getConnection(AbstractPoolBackedDataSource.java:128)
at org.springframework.jdbc.datasource.DataSourceUtils.doGetConnection(DataSourceUtils.java:111)
at org.springframework.jdbc.datasource.DataSourceUtils.getConnection(DataSourceUtils.java:77)
at org.mybatis.spring.transaction.SpringManagedTransaction.openConnection(SpringManagedTransaction.java:81)
at org.mybatis.spring.transaction.SpringManagedTransaction.getConnection(SpringManagedTransaction.java:67)
at org.apache.ibatis.executor.BaseExecutor.getConnection(BaseExecutor.java:279)
at org.apache.ibatis.executor.SimpleExecutor.prepareStatement(SimpleExecutor.java:72)
at org.apache.ibatis.executor.SimpleExecutor.doQuery(SimpleExecutor.java:59)
at org.apache.ibatis.executor.BaseExecutor.queryFromDatabase(BaseExecutor.java:267)
at org.apache.ibatis.executor.BaseExecutor.query(BaseExecutor.java:137)
at org.apache.ibatis.executor.CachingExecutor.query(CachingExecutor.java:96)
at org.apache.ibatis.executor.CachingExecutor.query(CachingExecutor.java:77)
at org.apache.ibatis.session.defaults.DefaultSqlSession.selectList(DefaultSqlSession.java:108)
at org.apache.ibatis.session.defaults.DefaultSqlSession.selectList(DefaultSqlSession.java:102)

通常在日志中包含上述信息之后,其紧接着的上下面会包含类似如下信息:

17-03-08 16:37:00 DEBUG com.mchange.v2.async.ThreadPoolAsynchronousRunner$PoolThread-#2 com.mchange.v2.resourcepool.BasicResourcePool: Preparing to destroy resource: com.mchange.v2.c3p0.impl.NewPooledConnectio
n@1070779f
17-03-08 16:37:00 DEBUG com.mchange.v2.async.ThreadPoolAsynchronousRunner$PoolThread-#2 com.mchange.v2.c3p0.impl.C3P0PooledConnectionPool: Preparing to destroy PooledConnection: com.mchange.v2.c3p0.impl.NewPoo
ledConnection@1070779f

17-03-08 16:37:00 DEBUG com.mchange.v2.async.ThreadPoolAsynchronousRunner$PoolThread-#2 com.mchange.v2.c3p0.impl.NewPooledConnection: com.mchange.v2.c3p0.impl.NewPooledConnection@1070779f closed by a client.
java.lang.Exception: DEBUG -- CLOSE BY CLIENT STACK TRACE
at com.mchange.v2.c3p0.impl.NewPooledConnection.close(NewPooledConnection.java:566)
at com.mchange.v2.c3p0.impl.NewPooledConnection.close(NewPooledConnection.java:234)
at com.mchange.v2.c3p0.impl.C3P0PooledConnectionPool$1PooledConnectionResourcePoolManager.destroyResource(C3P0PooledConnectionPool.java:470)
at com.mchange.v2.resourcepool.BasicResourcePool$1DestroyResourceTask.run(BasicResourcePool.java:964)
at com.mchange.v2.async.ThreadPoolAsynchronousRunner$PoolThread.run(ThreadPoolAsynchronousRunner.java:547)
17-03-08 16:37:00 DEBUG com.mchange.v2.async.ThreadPoolAsynchronousRunner$PoolThread-#2 com.mchange.v2.c3p0.impl.C3P0PooledConnectionPool: Successfully destroyed PooledConnection: com.mchange.v2.c3p0.impl.NewP
ooledConnection@1070779f
17-03-08 16:37:00 DEBUG com.mchange.v2.async.ThreadPoolAsynchronousRunner$PoolThread-#2 com.mchange.v2.resourcepool.BasicResourcePool: Successfully destroyed resource: com.mchange.v2.c3p0.impl.NewPooledConnect
ion@1070779f

比如initializeAutomaticTestTable处源码为:

    // only called from sync'ed methods
    private String initializeAutomaticTestTable(String automaticTestTable, DbAuth auth) throws SQLException
    {
        PooledConnection throwawayPooledConnection =    auth.equals( defaultAuth ) ? 
                                                        cpds.getPooledConnection() : 
                                                        cpds.getPooledConnection(auth.getUser(), auth.getPassword()); 
        Connection c = null;
        PreparedStatement testStmt = null;
        PreparedStatement createStmt = null;
        ResultSet mdrs = null;
        ResultSet rs = null;
        boolean exists;
        boolean has_rows;
        String out;
        try
        {
            c = throwawayPooledConnection.getConnection();

            DatabaseMetaData dmd = c.getMetaData();
            String q = dmd.getIdentifierQuoteString();
            String quotedTableName = q + automaticTestTable + q;
            out = "SELECT * FROM " + quotedTableName;
            mdrs = dmd.getTables( null, null, automaticTestTable, new String[] {"TABLE"} );
            exists = mdrs.next();

            //System.err.println("Table " + automaticTestTable + " exists? " + exists);

            if (exists)
            {
                testStmt = c.prepareStatement( out );
                rs = testStmt.executeQuery();
                has_rows = rs.next();
                if (has_rows)
                    throw new SQLException("automatic test table '" + automaticTestTable + 
                                    "' contains rows, and it should not! Please set this " +
                                    "parameter to the name of a table c3p0 can create on its own, " +
                    "that is not used elsewhere in the database!");
            }
            else
            {
                String createSql = "CREATE TABLE " + quotedTableName + " ( a CHAR(1) )";
                try
                {
                    createStmt = c.prepareStatement( createSql );
                    createStmt.executeUpdate();
                }
                catch (SQLException e)
                {
                    if (logger.isLoggable( MLevel.WARNING ))
                        logger.log(MLevel.WARNING, 
                                        "An attempt to create an automatic test table failed. Create SQL: " +
                                        createSql,
                                        e );
                    throw e;
                }
            }
            return out;
        }
        finally
        { 
            ResultSetUtils.attemptClose( mdrs );
            ResultSetUtils.attemptClose( rs );
            StatementUtils.attemptClose( testStmt );
            StatementUtils.attemptClose( createStmt );
            ConnectionUtils.attemptClose( c ); 
            try{ if (throwawayPooledConnection != null) throwawayPooledConnection.close(); }
            catch ( Exception e ) 
            { 
                //e.printStackTrace(); 
                logger.log(MLevel.WARNING, "A PooledConnection failed to close.", e);
            }
        }
    }

 

可知,它是被开发人员有意关闭的。

比如上面的close原因是idle超过时间,还有初始化c3p0test表后该连接主动关闭,当然还可能有其他原因。close出的关键源码如下:

    private void close( Throwable cause ) throws SQLException
    {
        if ( this.invalidatingException == null )
        {
            List closeExceptions = new LinkedList();

            // cleanup ResultSets
            cleanupResultSets( closeExceptions );

            // cleanup uncached Statements
            cleanupUncachedStatements( closeExceptions );

            // cleanup cached Statements
            try
            { closeAllCachedStatements(); }
            catch ( SQLException e )
            { closeExceptions.add(e); }

            // cleanup physicalConnection
            try
            { physicalConnection.close(); }
            catch ( SQLException e )
            {
                if (logger.isLoggable( MLevel.FINER ))
                    logger.log( MLevel.FINER, "Failed to close physical Connection: " + physicalConnection, e );

                closeExceptions.add(e); 
            }

            // update our state to bad status and closed, and log any exceptions
            if ( connection_status == ConnectionTester.CONNECTION_IS_OKAY )
                connection_status = ConnectionTester.CONNECTION_IS_INVALID;
            if ( cause == null )
            {
                this.invalidatingException = NORMAL_CLOSE_PLACEHOLDER;

                if ( logger.isLoggable( MLevel.FINEST ) )
                    logger.log( MLevel.FINEST, this + " closed by a client.", new Exception("DEBUG -- CLOSE BY CLIENT STACK TRACE") );

                logCloseExceptions( null, closeExceptions );

                if (closeExceptions.size() > 0)
                    throw new SQLException("Some resources failed to close properly while closing " + this);
            }
            else
            {
                this.invalidatingException = cause;
                if (Debug.TRACE >= Debug.TRACE_MED)
                    logCloseExceptions( cause, closeExceptions );
                else
                    logCloseExceptions( cause, null );
            }
        }
    }

从上面的流程+日志,我们也可确定它是被有意关闭的。所以确定c3p0的这些日志原因和作用还是要通过上下文代码来理解。在看之前,网上搜了一遍,讲得目的不对马嘴,就像一个中学生问“如何才能英语考高分”,你却回答人家“为什么要学英语”。

posted @ 2017-03-08 17:09  zhjh256  阅读(1327)  评论(0编辑  收藏  举报