zoukankan      html  css  js  c++  java
  • java.lang.Exception: DEBUG -- CLOSE BY CLIENT STACK TRACE 的理解

    [2013-12-06 11:06:21,715] [C3P0PooledConnectionPoolManager[identityToken->2tl0n98y1iwg7cbdzzq7a|719f1f]-HelperThread-#2] DEBUG - com.mchange.v2.c3p0.impl.NewPooledConnection@484c6b closed by a client.
    java.lang.Exception: DEBUG -- CLOSE BY CLIENT STACK TRACE
        at com.mchange.v2.c3p0.impl.NewPooledConnection.close(NewPooledConnection.java:646)
        at com.mchange.v2.c3p0.impl.NewPooledConnection.closeMaybeCheckedOut(NewPooledConnection.java:259)
        at com.mchange.v2.c3p0.impl.C3P0PooledConnectionPool$1PooledConnectionResourcePoolManager.destroyResource(C3P0PooledConnectionPool.java:619)
        at com.mchange.v2.resourcepool.BasicResourcePool$1DestroyResourceTask.run(BasicResourcePool.java:1024)
        at com.mchange.v2.async.ThreadPoolAsynchronousRunner$PoolThread.run(ThreadPoolAsynchronousRunner.java:648)
    [2013-12-06 11:06:21,716] [C3P0PooledConnectionPoolManager[identityToken->2tl0n98y1iwg7cbdzzq7a|719f1f]-HelperThread-#2] DEBUG - Successfully destroyed PooledConnection: com.mchange.v2.c3p0.impl.NewPooledConnection@484c6b

    经过分析源码,得到的结论是这个异常可以无视掉。
    相关源码如下(c3p0版本:c3p0-0.9.2.1):
    package com.mchange.v2.c3p0.impl;
    
    import java.util.*;
    import java.sql.*;
    import javax.sql.*;
    import com.mchange.v2.c3p0.*;
    import com.mchange.v2.c3p0.stmt.*;
    import com.mchange.v2.c3p0.util.*;
    import com.mchange.v2.log.*;
    
    import java.lang.reflect.Method;
    import com.mchange.v2.lang.ObjectUtils;
    import com.mchange.v2.sql.SqlUtils;
    
    public final class NewPooledConnection extends AbstractC3P0PooledConnection{
    
        private final static MLogger logger = MLog.getLogger( NewPooledConnection.class );
    //  methods below must be called from sync'ed methods
    
        /*
         *  If a throwable cause is provided, the PooledConnection is known to be broken (cause is an invalidating exception)
         *  and this method will not throw any exceptions, even if some resource closes fail.
         *
         *  If cause is null, then we think the PooledConnection is healthy, and we will report (throw) an exception
         *  if resources unexpectedlay fail to close.
         */
        private void close( Throwable cause ) throws SQLException
        { close( cause, false ); }
    
        private void close( Throwable cause, boolean forced ) throws SQLException
        {
        assert Thread.holdsLock( this );
    
            if ( this.invalidatingException == null )
            {
                List closeExceptions = new LinkedList();
    
                // cleanup ResultSets
                cleanupResultSets( closeExceptions );
    
                // cleanup uncached Statements
            // System.err.println(this + ".close( ... ) -- uncachedActiveStatements: " + uncachedActiveStatements);
                cleanupUncachedStatements( closeExceptions );
    
                // cleanup cached Statements
                try
                { closeAllCachedStatements(); }
                catch ( SQLException e )
                { closeExceptions.add(e); }
    
            if ( forced )
            {
                // reset transaction state
                try { C3P0ImplUtils.resetTxnState( physicalConnection, forceIgnoreUnresolvedTransactions, autoCommitOnClose, false ); }
                catch (Exception e)
                {
                    if (logger.isLoggable( MLevel.FINER ))
                    logger.log( MLevel.FINER, 
                            "Failed to reset the transaction state of  " + physicalConnection + "just prior to close(). " +
                            "Only relevant at all if this was a Connection being forced close()ed midtransaction.", 
                            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 ( Debug.DEBUG && logger.isLoggable( MLevel.FINEST ) )
                        logger.log( MLevel.FINEST, this + " closed by a client.", new Exception("DEBUG -- CLOSE BY CLIENT STACK TRACE") );//num:646 in the NewPooledConnection.java
    /*                

    Note that:
    1、This is not an exception, the new Exception is used merely to show execution path for debug purposes.
    2、And yes, this is only a debug message (actually, FINEST is the lowest possible level in java.util.logging).
    To wrap this up: ignore and tune your logging levels to skip these.

    http://stackoverflow.com/questions/8403227/weird-error-close-by-client-stack-trace

    既然成功了,干嘛还要丢异常出来?

    这里就不得不说到两个商业开发的原则问题了。
    第一,对上家传入数据严加过滤,对传出给下家的数据仔细检查。
    第二,合理使用异常。
    第一点其实很简单的。也就是模块化开发的一个思想问题。对自己的行为负责。前端返回的数据究竟是什么,需要进行校验。不合格的剔除或者是修正。合格的处理完后,在传出之前也要加以校验,是否合格

    结合到 “合理使用异常” 这句话来说呢,就是说,需要抛出异常的时候,就抛出。不需要抛出的时候,就不抛出。对程序员来说,在必要的时候看到一串异常信息,是最合适的事情了。

    http://www.zhixing123.cn/jsp/23305.html

     

    */

                     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 );
                }
            }
        }
     
    相关类:
    /********************************************************************
     * This class generated by com.mchange.v2.debug.DebugGen
     * and will probably be overwritten by the same! Edit at
     * YOUR PERIL!!! Hahahahaha.
     ********************************************************************/
    
    package com.mchange.v2.c3p0.impl;
    
    import com.mchange.v2.debug.DebugConstants;
    
    final class Debug implements DebugConstants
    {
        final static boolean DEBUG = true;
        final static int     TRACE = TRACE_MAX;
    
        private Debug()
        {}
    }
     
    package com.mchange.v2.log;
    
    import java.util.*;
    
    public final class MLevel
    {
        public final static MLevel ALL;
        public final static MLevel CONFIG;
        public final static MLevel FINE;
        public final static MLevel FINER;
        public final static MLevel FINEST;
        public final static MLevel INFO;
        public final static MLevel OFF;
        public final static MLevel SEVERE;
        public final static MLevel WARNING;
    
        private final static Map integersToMLevels;
        private final static Map namesToMLevels;
    
        public static MLevel fromIntValue(int intval)
        { return (MLevel) integersToMLevels.get( new Integer( intval ) ); }
    
        public static MLevel fromSeverity(String name)
        { return (MLevel) namesToMLevels.get( name ); }
    
        static
        {
        Class lvlClass;
        boolean jdk14api;  //not just jdk14 -- it is possible for the api to be present with older vms
        try
            { 
            lvlClass = Class.forName( "java.util.logging.Level" ); 
            jdk14api = true;
            }
        catch (ClassNotFoundException e )
            { 
            lvlClass = null;
            jdk14api = false; 
            }
    
        MLevel all;
        MLevel config;
        MLevel fine;
        MLevel finer;
        MLevel finest;
        MLevel info;
        MLevel off;
        MLevel severe;
        MLevel warning;
    
        try
            { 
            // numeric values match the intvalues from java.util.logging.Level
            all = new MLevel( (jdk14api ? lvlClass.getField("ALL").get(null) : null), Integer.MIN_VALUE, "ALL" );
            config = new MLevel( (jdk14api ? lvlClass.getField("CONFIG").get(null) : null), 700, "CONFIG" );
            fine = new MLevel( (jdk14api ? lvlClass.getField("FINE").get(null) : null), 500, "FINE" );
            finer = new MLevel( (jdk14api ? lvlClass.getField("FINER").get(null) : null), 400, "FINER" );
            finest = new MLevel( (jdk14api ? lvlClass.getField("FINEST").get(null) : null), 300, "FINEST" );
            info = new MLevel( (jdk14api ? lvlClass.getField("INFO").get(null) : null), 800, "INFO" );
            off = new MLevel( (jdk14api ? lvlClass.getField("OFF").get(null) : null), Integer.MAX_VALUE, "OFF" );
            severe = new MLevel( (jdk14api ? lvlClass.getField("SEVERE").get(null) : null), 900, "SEVERE" );
            warning = new MLevel( (jdk14api ? lvlClass.getField("WARNING").get(null) : null), 1000, "WARNING" );
            }
        catch ( Exception e )
            { 
            e.printStackTrace();
            throw new InternalError("Huh? java.util.logging.Level is here, but not its expected public fields?");
            }
    
        ALL = all;
        CONFIG = config;
        FINE = fine;
        FINER = finer;
        FINEST = finest;
        INFO = info;
        OFF = off;
        SEVERE = severe;
        WARNING = warning;
    
        Map tmp = new HashMap();
        tmp.put( new Integer(all.intValue()), all);
        tmp.put( new Integer(config.intValue()), config);
        tmp.put( new Integer(fine.intValue()), fine);
        tmp.put( new Integer(finer.intValue()), finer);
        tmp.put( new Integer(finest.intValue()), finest);
        tmp.put( new Integer(info.intValue()), info);
        tmp.put( new Integer(off.intValue()), off);
        tmp.put( new Integer(severe.intValue()), severe);
        tmp.put( new Integer(warning.intValue()), warning);
    
        integersToMLevels = Collections.unmodifiableMap( tmp );
    
        tmp = new HashMap();
        tmp.put( all.getSeverity(), all);
        tmp.put( config.getSeverity(), config);
        tmp.put( fine.getSeverity(), fine);
        tmp.put( finer.getSeverity(), finer);
        tmp.put( finest.getSeverity(), finest);
        tmp.put( info.getSeverity(), info);
        tmp.put( off.getSeverity(), off);
        tmp.put( severe.getSeverity(), severe);
        tmp.put( warning.getSeverity(), warning);
    
        namesToMLevels = Collections.unmodifiableMap( tmp );
        }
    
        Object level;
        int    intval;
        String lvlstring;
    
        public int intValue()
        { return intval; }
    
        public Object asJdk14Level()
        { return level; }
    
        public String getSeverity()
        { return lvlstring; }
    
        public String toString()
        { return this.getClass().getName() + this.getLineHeader(); }
    
        public String getLineHeader()
        { return "[" + lvlstring + ']';}
    
        public boolean isLoggable( MLevel filterLevel )
        { return this.intval >= filterLevel.intval; }
    
        private MLevel(Object level, int intval, String lvlstring)
        {
        this.level = level;
        this.intval = intval;
        this.lvlstring = lvlstring;
        }
    }
     

     

    package java.util.logging;
    
    import java.util.*;
    import java.security.*;
    import java.lang.ref.WeakReference;
     
    private static final int offValue = Level.OFF.intValue();
        private volatile int levelValue;  // current effective level value
        /** * Check if a message of the given level would actually be logged
     * by this logger. This check is based on the Loggers effective level,
     * which may be inherited from its parent. *
     * @param level a message logging level
     * @return true if the given message level is currently being logged. */
        public boolean isLoggable(Level level) {
        if (level.intValue() < levelValue || levelValue == offValue) {
            return false;    }    return true;    }
  • 相关阅读:
    linux 下安装mongodb
    python 多线程, 多进程, 协程
    5.rabbitmq 主题
    4.rabbitmq 路由
    e.target与e.currentTarget对比
    使用ffmpeg下载m3u8流媒体
    本机添加多个git仓库账号
    IE hack 条件语句
    IE8 兼容 getElementsByClassName
    IE 下 log 调试的一点不同
  • 原文地址:https://www.cnblogs.com/softidea/p/3461838.html
Copyright © 2011-2022 走看看