    001/*
    002 * Licensed to the Apache Software Foundation (ASF) under one or more
    003 * contributor license agreements.  See the NOTICE file distributed with
    004 * this work for additional information regarding copyright ownership.
    005 * The ASF licenses this file to You under the Apache License, Version 2.0
    006 * (the "License"); you may not use this file except in compliance with
    007 * the License.  You may obtain a copy of the License at
    008 *
    009 *      http://www.apache.org/licenses/LICENSE-2.0
    010 *
    011 * Unless required by applicable law or agreed to in writing, software
    012 * distributed under the License is distributed on an "AS IS" BASIS,
    013 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
    014 * See the License for the specific language governing permissions and
    015 * limitations under the License.
    016 */
    017package org.apache.commons.pool2.impl;
    018
    019import java.util.ArrayList;
    020import java.util.HashSet;
    021import java.util.Iterator;
    022import java.util.Map;
    023import java.util.NoSuchElementException;
    024import java.util.Set;
    025import java.util.concurrent.ConcurrentHashMap;
    026import java.util.concurrent.TimeUnit;
    027import java.util.concurrent.atomic.AtomicLong;
    028
    029import org.apache.commons.pool2.ObjectPool;
    030import org.apache.commons.pool2.PoolUtils;
    031import org.apache.commons.pool2.PooledObject;
    032import org.apache.commons.pool2.PooledObjectFactory;
    033import org.apache.commons.pool2.PooledObjectState;
    034import org.apache.commons.pool2.SwallowedExceptionListener;
    035import org.apache.commons.pool2.TrackedUse;
    036import org.apache.commons.pool2.UsageTracking;
    037
    038/**
    039 * A configurable {@link ObjectPool} implementation.
    040 * <p>
    041 * When coupled with the appropriate {@link PooledObjectFactory},
    042 * <code>GenericObjectPool</code> provides robust pooling functionality for
    043 * arbitrary objects.</p>
    044 * <p>
    045 * Optionally, one may configure the pool to examine and possibly evict objects
    046 * as they sit idle in the pool and to ensure that a minimum number of idle
    047 * objects are available. This is performed by an "idle object eviction" thread,
    048 * which runs asynchronously. Caution should be used when configuring this
    049 * optional feature. Eviction runs contend with client threads for access to
    050 * objects in the pool, so if they run too frequently performance issues may
    051 * result.</p>
    052 * <p>
    053 * The pool can also be configured to detect and remove "abandoned" objects,
    054 * i.e. objects that have been checked out of the pool but neither used nor
    055 * returned before the configured
    056 * {@link AbandonedConfig#getRemoveAbandonedTimeout() removeAbandonedTimeout}.
    057 * Abandoned object removal can be configured to happen when
    058 * <code>borrowObject</code> is invoked and the pool is close to starvation, or
    059 * it can be executed by the idle object evictor, or both. If pooled objects
    060 * implement the {@link TrackedUse} interface, their last use will be queried
    061 * using the <code>getLastUsed</code> method on that interface; otherwise
    062 * abandonment is determined by how long an object has been checked out from
    063 * the pool.</p>
    064 * <p>
    065 * Implementation note: To prevent possible deadlocks, care has been taken to
    066 * ensure that no call to a factory method will occur within a synchronization
    067 * block. See POOL-125 and DBCP-44 for more information.</p>
    068 * <p>
    069 * This class is intended to be thread-safe.</p>
    070 *
    071 * @see GenericKeyedObjectPool
    072 *
    073 * @param <T> Type of element pooled in this pool.
    074 *
    075 * @version $Revision: 1545920 $
    076 *
    077 * @since 2.0
    078 */
    079public class GenericObjectPool<T> extends BaseGenericObjectPool<T>
    080        implements ObjectPool<T>, GenericObjectPoolMXBean, UsageTracking<T> {
    081
    082    /**
    083     * Create a new <code>GenericObjectPool</code> using defaults from
    084     * {@link GenericObjectPoolConfig}.
    085     *
    086     * @param factory The object factory to be used to create object instances
    087     *                used by this pool
    088     */
    089    public GenericObjectPool(PooledObjectFactory<T> factory) {
    090        this(factory, new GenericObjectPoolConfig());
    091    }
    092
    093    /**
    094     * Create a new <code>GenericObjectPool</code> using a specific
    095     * configuration.
    096     *
    097     * @param factory   The object factory to be used to create object instances
    098     *                  used by this pool
    099     * @param config    The configuration to use for this pool instance. The
    100     *                  configuration is used by value. Subsequent changes to
    101     *                  the configuration object will not be reflected in the
    102     *                  pool.
    103     */
    104    public GenericObjectPool(PooledObjectFactory<T> factory,
    105            GenericObjectPoolConfig config) {
    106
    107        super(config, ONAME_BASE, config.getJmxNamePrefix());
    108
    109        if (factory == null) {
    110            jmxUnregister(); // tidy up
    111            throw new IllegalArgumentException("factory may not be null");
    112        }
    113        this.factory = factory;
    114
    115        setConfig(config);
    116
    117        startEvictor(getTimeBetweenEvictionRunsMillis());
    118    }
    119
    120    /**
    121     * Create a new <code>GenericObjectPool</code> that tracks and destroys
    122     * objects that are checked out, but never returned to the pool.
    123     *
    124     * @param factory   The object factory to be used to create object instances
    125     *                  used by this pool
    126     * @param config    The base pool configuration to use for this pool instance.
    127     *                  The configuration is used by value. Subsequent changes to
    128     *                  the configuration object will not be reflected in the
    129     *                  pool.
    130     * @param abandonedConfig  Configuration for abandoned object identification
    131     *                         and removal.  The configuration is used by value.
    132     */
    133    public GenericObjectPool(PooledObjectFactory<T> factory,
    134            GenericObjectPoolConfig config, AbandonedConfig abandonedConfig) {
    135        this(factory, config);
    136        setAbandonedConfig(abandonedConfig);
    137    }
    138
    139    /**
    140     * Returns the cap on the number of "idle" instances in the pool. If maxIdle
    141     * is set too low on heavily loaded systems it is possible you will see
    142     * objects being destroyed and almost immediately new objects being created.
    143     * This is a result of the active threads momentarily returning objects
    144     * faster than they are requesting them them, causing the number of idle
    145     * objects to rise above maxIdle. The best value for maxIdle for heavily
    146     * loaded system will vary but the default is a good starting point.
    147     *
    148     * @return the maximum number of "idle" instances that can be held in the
    149     *         pool or a negative value if there is no limit
    150     *
    151     * @see #setMaxIdle
    152     */
    153    @Override
    154    public int getMaxIdle() {
    155        return maxIdle;
    156    }
    157
    158    /**
    159     * Returns the cap on the number of "idle" instances in the pool. If maxIdle
    160     * is set too low on heavily loaded systems it is possible you will see
    161     * objects being destroyed and almost immediately new objects being created.
    162     * This is a result of the active threads momentarily returning objects
    163     * faster than they are requesting them them, causing the number of idle
    164     * objects to rise above maxIdle. The best value for maxIdle for heavily
    165     * loaded system will vary but the default is a good starting point.
    166     *
    167     * @param maxIdle
    168     *            The cap on the number of "idle" instances in the pool. Use a
    169     *            negative value to indicate an unlimited number of idle
    170     *            instances
    171     *
    172     * @see #getMaxIdle
    173     */
    174    public void setMaxIdle(int maxIdle) {
    175        this.maxIdle = maxIdle;
    176    }
    177
    178    /**
    179     * Sets the target for the minimum number of idle objects to maintain in
    180     * the pool. This setting only has an effect if it is positive and
    181     * {@link #getTimeBetweenEvictionRunsMillis()} is greater than zero. If this
    182     * is the case, an attempt is made to ensure that the pool has the required
    183     * minimum number of instances during idle object eviction runs.
    184     * <p>
    185     * If the configured value of minIdle is greater than the configured value
    186     * for maxIdle then the value of maxIdle will be used instead.
    187     *
    188     * @param minIdle
    189     *            The minimum number of objects.
    190     *
    191     * @see #getMinIdle()
    192     * @see #getMaxIdle()
    193     * @see #getTimeBetweenEvictionRunsMillis()
    194     */
    195    public void setMinIdle(int minIdle) {
    196        this.minIdle = minIdle;
    197    }
    198
    199    /**
    200     * Returns the target for the minimum number of idle objects to maintain in
    201     * the pool. This setting only has an effect if it is positive and
    202     * {@link #getTimeBetweenEvictionRunsMillis()} is greater than zero. If this
    203     * is the case, an attempt is made to ensure that the pool has the required
    204     * minimum number of instances during idle object eviction runs.
    205     * <p>
    206     * If the configured value of minIdle is greater than the configured value
    207     * for maxIdle then the value of maxIdle will be used instead.
    208     *
    209     * @return The minimum number of objects.
    210     *
    211     * @see #setMinIdle(int)
    212     * @see #setMaxIdle(int)
    213     * @see #setTimeBetweenEvictionRunsMillis(long)
    214     */
    215    @Override
    216    public int getMinIdle() {
    217        int maxIdleSave = getMaxIdle();
    218        if (this.minIdle > maxIdleSave) {
    219            return maxIdleSave;
    220        } else {
    221            return minIdle;
    222        }
    223    }
    224
    225    /**
    226     * Whether or not abandoned object removal is configured for this pool.
    227     *
    228     * @return true if this pool is configured to detect and remove
    229     * abandoned objects
    230     */
    231    @Override
    232    public boolean isAbandonedConfig() {
    233        return abandonedConfig != null;
    234    }
    235
    236    /**
    237     * Will this pool identify and log any abandoned objects?
    238     *
    239     * @return {@code true} if abandoned object removal is configured for this
    240     *         pool and removal events are to be logged otherwise {@code false}
    241     *
    242     * @see AbandonedConfig#getLogAbandoned()
    243     */
    244    @Override
    245    public boolean getLogAbandoned() {
    246        AbandonedConfig ac = this.abandonedConfig;
    247        return ac != null && ac.getLogAbandoned();
    248    }
    249
    250    /**
    251     * Will a check be made for abandoned objects when an object is borrowed
    252     * from this pool?
    253     *
    254     * @return {@code true} if abandoned object removal is configured to be
    255     *         activated by borrowObject otherwise {@code false}
    256     *
    257     * @see AbandonedConfig#getRemoveAbandonedOnBorrow()
    258     */
    259    @Override
    260    public boolean getRemoveAbandonedOnBorrow() {
    261        AbandonedConfig ac = this.abandonedConfig;
    262        return ac != null && ac.getRemoveAbandonedOnBorrow();
    263    }
    264
    265    /**
    266     * Will a check be made for abandoned objects when the evictor runs?
    267     *
    268     * @return {@code true} if abandoned object removal is configured to be
    269     *         activated when the evictor runs otherwise {@code false}
    270     *
    271     * @see AbandonedConfig#getRemoveAbandonedOnMaintenance()
    272     */
    273    @Override
    274    public boolean getRemoveAbandonedOnMaintenance() {
    275        AbandonedConfig ac = this.abandonedConfig;
    276        return ac != null && ac.getRemoveAbandonedOnMaintenance();
    277    }
    278
    279    /**
    280     * Obtain the timeout before which an object will be considered to be
    281     * abandoned by this pool.
    282     *
    283     * @return The abandoned object timeout in seconds if abandoned object
    284     *         removal is configured for this pool; Integer.MAX_VALUE otherwise.
    285     *
    286     * @see AbandonedConfig#getRemoveAbandonedTimeout()
    287     */
    288    @Override
    289    public int getRemoveAbandonedTimeout() {
    290        AbandonedConfig ac = this.abandonedConfig;
    291        return ac != null ? ac.getRemoveAbandonedTimeout() : Integer.MAX_VALUE;
    292    }
    293
    294
    295    /**
    296     * Sets the base pool configuration.
    297     *
    298     * @param conf the new configuration to use. This is used by value.
    299     *
    300     * @see GenericObjectPoolConfig
    301     */
    302    public void setConfig(GenericObjectPoolConfig conf) {
    303        setLifo(conf.getLifo());
    304        setMaxIdle(conf.getMaxIdle());
    305        setMinIdle(conf.getMinIdle());
    306        setMaxTotal(conf.getMaxTotal());
    307        setMaxWaitMillis(conf.getMaxWaitMillis());
    308        setBlockWhenExhausted(conf.getBlockWhenExhausted());
    309        setTestOnBorrow(conf.getTestOnBorrow());
    310        setTestOnReturn(conf.getTestOnReturn());
    311        setTestWhileIdle(conf.getTestWhileIdle());
    312        setNumTestsPerEvictionRun(conf.getNumTestsPerEvictionRun());
    313        setMinEvictableIdleTimeMillis(conf.getMinEvictableIdleTimeMillis());
    314        setTimeBetweenEvictionRunsMillis(
    315                conf.getTimeBetweenEvictionRunsMillis());
    316        setSoftMinEvictableIdleTimeMillis(
    317                conf.getSoftMinEvictableIdleTimeMillis());
    318        setEvictionPolicyClassName(conf.getEvictionPolicyClassName());
    319    }
    320
    321    /**
    322     * Sets the abandoned object removal configuration.
    323     *
    324     * @param abandonedConfig the new configuration to use. This is used by value.
    325     *
    326     * @see AbandonedConfig
    327     */
    328    public void setAbandonedConfig(AbandonedConfig abandonedConfig) throws IllegalArgumentException {
    329        if (abandonedConfig == null) {
    330            this.abandonedConfig = null;
    331        } else {
    332            this.abandonedConfig = new AbandonedConfig();
    333            this.abandonedConfig.setLogAbandoned(abandonedConfig.getLogAbandoned());
    334            this.abandonedConfig.setLogWriter(abandonedConfig.getLogWriter());
    335            this.abandonedConfig.setRemoveAbandonedOnBorrow(abandonedConfig.getRemoveAbandonedOnBorrow());
    336            this.abandonedConfig.setRemoveAbandonedOnMaintenance(abandonedConfig.getRemoveAbandonedOnMaintenance());
    337            this.abandonedConfig.setRemoveAbandonedTimeout(abandonedConfig.getRemoveAbandonedTimeout());
    338            this.abandonedConfig.setUseUsageTracking(abandonedConfig.getUseUsageTracking());
    339        }
    340    }
    341
    342    /**
    343     * Obtain a reference to the factory used to create, destroy and validate
    344     * the objects used by this pool.
    345     *
    346     * @return the factory
    347     */
    348    public PooledObjectFactory<T> getFactory() {
    349        return factory;
    350    }
    351
    352    /**
    353     * Equivalent to <code>{@link #borrowObject(long)
    354     * borrowObject}({@link #getMaxWaitMillis()})</code>.
    355     * <p>
    356     * {@inheritDoc}
    357     */
    358    @Override
    359    public T borrowObject() throws Exception {
    360        return borrowObject(getMaxWaitMillis());
    361    }
    362
    363    /**
    364     * Borrow an object from the pool using the specific waiting time which only
    365     * applies if {@link #getBlockWhenExhausted()} is true.
    366     * <p>
    367     * If there is one or more idle instance available in the pool, then an
    368     * idle instance will be selected based on the value of {@link #getLifo()},
    369     * activated and returned. If activation fails, or {@link #getTestOnBorrow()
    370     * testOnBorrow} is set to <code>true</code> and validation fails, the
    371     * instance is destroyed and the next available instance is examined. This
    372     * continues until either a valid instance is returned or there are no more
    373     * idle instances available.
    374     * <p>
    375     * If there are no idle instances available in the pool, behavior depends on
    376     * the {@link #getMaxTotal() maxTotal}, (if applicable)
    377     * {@link #getBlockWhenExhausted()} and the value passed in to the
    378     * <code>borrowMaxWaitMillis</code> parameter. If the number of instances
    379     * checked out from the pool is less than <code>maxTotal,</code> a new
    380     * instance is created, activated and (if applicable) validated and returned
    381     * to the caller.
    382     * <p>
    383     * If the pool is exhausted (no available idle instances and no capacity to
    384     * create new ones), this method will either block (if
    385     * {@link #getBlockWhenExhausted()} is true) or throw a
    386     * <code>NoSuchElementException</code> (if
    387     * {@link #getBlockWhenExhausted()} is false). The length of time that this
    388     * method will block when {@link #getBlockWhenExhausted()} is true is
    389     * determined by the value passed in to the <code>borrowMaxWaitMillis</code>
    390     * parameter.
    391     * <p>
    392     * When the pool is exhausted, multiple calling threads may be
    393     * simultaneously blocked waiting for instances to become available. A
    394     * "fairness" algorithm has been implemented to ensure that threads receive
    395     * available instances in request arrival order.
    396     *
    397     * @param borrowMaxWaitMillis The time to wait in milliseconds for an object
    398     *                            to become available
    399     *
    400     * @return object instance from the pool
    401     *
    402     * @throws NoSuchElementException if an instance cannot be returned
    403     */
    404    public T borrowObject(long borrowMaxWaitMillis) throws Exception {
    405        assertOpen();
    406
    407        AbandonedConfig ac = this.abandonedConfig;
    408        if (ac != null && ac.getRemoveAbandonedOnBorrow() &&
    409                (getNumIdle() < 2) &&
    410                (getNumActive() > getMaxTotal() - 3) ) {
    411            removeAbandoned(ac);
    412        }
    413
    414        PooledObject<T> p = null;
    415
    416        // Get local copy of current config so it is consistent for entire
    417        // method execution
    418        boolean blockWhenExhausted = getBlockWhenExhausted();
    419
    420        boolean create;
    421        long waitTime = 0;
    422
    423        while (p == null) {
    424            create = false;
    425            if (blockWhenExhausted) {
    426                p = idleObjects.pollFirst();
    427                if (p == null) {
    428                    create = true;
    429                    p = create();
    430                }
    431                if (p == null) {
    432                    if (borrowMaxWaitMillis < 0) {
    433                        p = idleObjects.takeFirst();
    434                    } else {
    435                        waitTime = System.currentTimeMillis();
    436                        p = idleObjects.pollFirst(borrowMaxWaitMillis,
    437                                TimeUnit.MILLISECONDS);
    438                        waitTime = System.currentTimeMillis() - waitTime;
    439                    }
    440                }
    441                if (p == null) {
    442                    throw new NoSuchElementException(
    443                            "Timeout waiting for idle object");
    444                }
    445                if (!p.allocate()) {
    446                    p = null;
    447                }
    448            } else {
    449                p = idleObjects.pollFirst();
    450                if (p == null) {
    451                    create = true;
    452                    p = create();
    453                }
    454                if (p == null) {
    455                    throw new NoSuchElementException("Pool exhausted");
    456                }
    457                if (!p.allocate()) {
    458                    p = null;
    459                }
    460            }
    461
    462            if (p != null) {
    463                try {
    464                    factory.activateObject(p);
    465                } catch (Exception e) {
    466                    try {
    467                        destroy(p);
    468                    } catch (Exception e1) {
    469                        // Ignore - activation failure is more important
    470                    }
    471                    p = null;
    472                    if (create) {
    473                        NoSuchElementException nsee = new NoSuchElementException(
    474                                "Unable to activate object");
    475                        nsee.initCause(e);
    476                        throw nsee;
    477                    }
    478                }
    479                if (p != null && getTestOnBorrow()) {
    480                    boolean validate = false;
    481                    Throwable validationThrowable = null;
    482                    try {
    483                        validate = factory.validateObject(p);
    484                    } catch (Throwable t) {
    485                        PoolUtils.checkRethrow(t);
    486                        validationThrowable = t;
    487                    }
    488                    if (!validate) {
    489                        try {
    490                            destroy(p);
    491                            destroyedByBorrowValidationCount.incrementAndGet();
    492                        } catch (Exception e) {
    493                            // Ignore - validation failure is more important
    494                        }
    495                        p = null;
    496                        if (create) {
    497                            NoSuchElementException nsee = new NoSuchElementException(
    498                                    "Unable to validate object");
    499                            nsee.initCause(validationThrowable);
    500                            throw nsee;
    501                        }
    502                    }
    503                }
    504            }
    505        }
    506
    507        updateStatsBorrow(p, waitTime);
    508
    509        return p.getObject();
    510    }
    511
    512    /**
    513     * Returns an object instance to the pool.
    514     * <p>
    515     * If {@link #getMaxIdle() maxIdle} is set to a positive value and the
    516     * number of idle instances has reached this value, the returning instance
    517     * is destroyed.
    518     * <p>
    519     * If {@link #getTestOnReturn() testOnReturn} == true, the returning
    520     * instance is validated before being returned to the idle instance pool. In
    521     * this case, if validation fails, the instance is destroyed.
    522     * <p>
    523     * Exceptions encountered destroying objects for any reason are swallowed
    524     * but notified via a {@link SwallowedExceptionListener}.
    525     *
    526     * @param obj instance to return to the pool
    527     */
    528    @Override
    529    public void returnObject(T obj) {
    530        PooledObject<T> p = allObjects.get(obj);
    531
    532        if (!isAbandonedConfig()) {
    533            if (p == null) {
    534                throw new IllegalStateException(
    535                        "Returned object not currently part of this pool");
    536            }
    537        } else {
    538            if (p == null) {
    539                return;  // Object was abandoned and removed
    540            } else {
    541                // Make sure object is not being reclaimed
    542                synchronized(p) {
    543                    final PooledObjectState state = p.getState();
    544                    if (state == PooledObjectState.ABANDONED ||
    545                            state == PooledObjectState.INVALID) {
    546                        return;
    547                    } else {
    548                        p.markReturning(); // Keep from being marked abandoned
    549                    }
    550                }
    551            }
    552        }
    553
    554        long activeTime = p.getActiveTimeMillis();
    555
    556        if (getTestOnReturn()) {
    557            if (!factory.validateObject(p)) {
    558                try {
    559                    destroy(p);
    560                } catch (Exception e) {
    561                    swallowException(e);
    562                }
    563                try {
    564                    ensureIdle(1, false);
    565                } catch (Exception e) {
    566                    swallowException(e);
    567                }
    568                updateStatsReturn(activeTime);
    569                return;
    570            }
    571        }
    572
    573        try {
    574            factory.passivateObject(p);
    575        } catch (Exception e1) {
    576            swallowException(e1);
    577            try {
    578                destroy(p);
    579            } catch (Exception e) {
    580                swallowException(e);
    581            }
    582            try {
    583                ensureIdle(1, false);
    584            } catch (Exception e) {
    585                swallowException(e);
    586            }
    587            updateStatsReturn(activeTime);
    588            return;
    589        }
    590
    591        if (!p.deallocate()) {
    592            throw new IllegalStateException(
    593                    "Object has already been retured to this pool or is invalid");
    594        }
    595
    596        int maxIdleSave = getMaxIdle();
    597        if (isClosed() || maxIdleSave > -1 && maxIdleSave <= idleObjects.size()) {
    598            try {
    599                destroy(p);
    600            } catch (Exception e) {
    601                swallowException(e);
    602            }
    603        } else {
    604            if (getLifo()) {
    605                idleObjects.addFirst(p);
    606            } else {
    607                idleObjects.addLast(p);
    608            }
    609        }
    610        updateStatsReturn(activeTime);
    611    }
    612
    613    /**
    614     * {@inheritDoc}
    615     * <p>
    616     * Activation of this method decrements the active count and attempts to
    617     * destroy the instance.
    618     *
    619     * @throws Exception             if an exception occurs destroying the
    620     *                               object
    621     * @throws IllegalStateException if obj does not belong to this pool
    622     */
    623    @Override
    624    public void invalidateObject(T obj) throws Exception {
    625        PooledObject<T> p = allObjects.get(obj);
    626        if (p == null) {
    627            if (isAbandonedConfig()) {
    628                return;
    629            } else {
    630                throw new IllegalStateException(
    631                        "Invalidated object not currently part of this pool");
    632            }
    633        }
    634        synchronized (p) {
    635            if (p.getState() != PooledObjectState.INVALID) {
    636                destroy(p);
    637            }
    638        }
    639        ensureIdle(1, false);
    640    }
    641
    642    /**
    643     * Clears any objects sitting idle in the pool by removing them from the
    644     * idle instance pool and then invoking the configured
    645     * {@link PooledObjectFactory#destroyObject(PooledObject)} method on each
    646     * idle instance.
    647     * <p>
    648     * Implementation notes:
    649     * <ul>
    650     * <li>This method does not destroy or effect in any way instances that are
    651     * checked out of the pool when it is invoked.</li>
    652     * <li>Invoking this method does not prevent objects being returned to the
    653     * idle instance pool, even during its execution. Additional instances may
    654     * be returned while removed items are being destroyed.</li>
    655     * <li>Exceptions encountered destroying idle instances are swallowed
    656     * but notified via a {@link SwallowedExceptionListener}.</li>
    657     * </ul>
    658     */
    659    @Override
    660    public void clear() {
    661        PooledObject<T> p = idleObjects.poll();
    662
    663        while (p != null) {
    664            try {
    665                destroy(p);
    666            } catch (Exception e) {
    667                swallowException(e);
    668            }
    669            p = idleObjects.poll();
    670        }
    671    }
    672
    673    @Override
    674    public int getNumActive() {
    675        return allObjects.size() - idleObjects.size();
    676    }
    677
    678    @Override
    679    public int getNumIdle() {
    680        return idleObjects.size();
    681    }
    682
    683    /**
    684     * Closes the pool. Once the pool is closed, {@link #borrowObject()} will
    685     * fail with IllegalStateException, but {@link #returnObject(Object)} and
    686     * {@link #invalidateObject(Object)} will continue to work, with returned
    687     * objects destroyed on return.
    688     * <p>
    689     * Destroys idle instances in the pool by invoking {@link #clear()}.
    690     */
    691    @Override
    692    public void close() {
    693        if (isClosed()) {
    694            return;
    695        }
    696
    697        synchronized (closeLock) {
    698            if (isClosed()) {
    699                return;
    700            }
    701
    702            // Stop the evictor before the pool is closed since evict() calls
    703            // assertOpen()
    704            startEvictor(-1L);
    705
    706            closed = true;
    707            // This clear removes any idle objects
    708            clear();
    709
    710            jmxUnregister();
    711
    712            // Release any threads that were waiting for an object
    713            idleObjects.interuptTakeWaiters();
    714        }
    715    }
    716
    717    /**
    718     * {@inheritDoc}
    719     * <p>
    720     * Successive activations of this method examine objects in sequence,
    721     * cycling through objects in oldest-to-youngest order.
    722     */
    723    @Override
    724    public void evict() throws Exception {
    725        assertOpen();
    726
    727        if (idleObjects.size() > 0) {
    728
    729            PooledObject<T> underTest = null;
    730            EvictionPolicy<T> evictionPolicy = getEvictionPolicy();
    731
    732            synchronized (evictionLock) {
    733                EvictionConfig evictionConfig = new EvictionConfig(
    734                        getMinEvictableIdleTimeMillis(),
    735                        getSoftMinEvictableIdleTimeMillis(),
    736                        getMinIdle());
    737
    738                boolean testWhileIdle = getTestWhileIdle();
    739
    740                for (int i = 0, m = getNumTests(); i < m; i++) {
    741                    if (evictionIterator == null || !evictionIterator.hasNext()) {
    742                        if (getLifo()) {
    743                            evictionIterator = idleObjects.descendingIterator();
    744                        } else {
    745                            evictionIterator = idleObjects.iterator();
    746                        }
    747                    }
    748                    if (!evictionIterator.hasNext()) {
    749                        // Pool exhausted, nothing to do here
    750                        return;
    751                    }
    752
    753                    try {
    754                        underTest = evictionIterator.next();
    755                    } catch (NoSuchElementException nsee) {
    756                        // Object was borrowed in another thread
    757                        // Don't count this as an eviction test so reduce i;
    758                        i--;
    759                        evictionIterator = null;
    760                        continue;
    761                    }
    762
    763                    if (!underTest.startEvictionTest()) {
    764                        // Object was borrowed in another thread
    765                        // Don't count this as an eviction test so reduce i;
    766                        i--;
    767                        continue;
    768                    }
    769
    770                    if (evictionPolicy.evict(evictionConfig, underTest,
    771                            idleObjects.size())) {
    772                        destroy(underTest);
    773                        destroyedByEvictorCount.incrementAndGet();
    774                    } else {
    775                        if (testWhileIdle) {
    776                            boolean active = false;
    777                            try {
    778                                factory.activateObject(underTest);
    779                                active = true;
    780                            } catch (Exception e) {
    781                                destroy(underTest);
    782                                destroyedByEvictorCount.incrementAndGet();
    783                            }
    784                            if (active) {
    785                                if (!factory.validateObject(underTest)) {
    786                                    destroy(underTest);
    787                                    destroyedByEvictorCount.incrementAndGet();
    788                                } else {
    789                                    try {
    790                                        factory.passivateObject(underTest);
    791                                    } catch (Exception e) {
    792                                        destroy(underTest);
    793                                        destroyedByEvictorCount.incrementAndGet();
    794                                    }
    795                                }
    796                            }
    797                        }
    798                        if (!underTest.endEvictionTest(idleObjects)) {
    799                            // TODO - May need to add code here once additional
    800                            // states are used
    801                        }
    802                    }
    803                }
    804            }
    805        }
    806        AbandonedConfig ac = this.abandonedConfig;
    807        if (ac != null && ac.getRemoveAbandonedOnMaintenance()) {
    808            removeAbandoned(ac);
    809        }
    810    }
    811
    812    /**
    813     * Attempts to create a new wrapped pooled object.
    814     * <p>
    815     * If there are {@link #getMaxTotal()} objects already in circulation
    816     * or in process of being created, this method returns null.
    817     *
    818     * @return The new wrapped pooled object
    819     *
    820     * @throws Exception if the object factory's {@code makeObject} fails
    821     */
    822    private PooledObject<T> create() throws Exception {
    823        int localMaxTotal = getMaxTotal();
    824        long newCreateCount = createCount.incrementAndGet();
    825        if (localMaxTotal > -1 && newCreateCount > localMaxTotal ||
    826                newCreateCount > Integer.MAX_VALUE) {
    827            createCount.decrementAndGet();
    828            return null;
    829        }
    830
    831        final PooledObject<T> p;
    832        try {
    833            p = factory.makeObject();
    834        } catch (Exception e) {
    835            createCount.decrementAndGet();
    836            throw e;
    837        }
    838
    839        AbandonedConfig ac = this.abandonedConfig;
    840        if (ac != null && ac.getLogAbandoned()) {
    841            p.setLogAbandoned(true);
    842        }
    843
    844        createdCount.incrementAndGet();
    845        allObjects.put(p.getObject(), p);
    846        return p;
    847    }
    848
    849    /**
    850     * Destroys a wrapped pooled object.
    851     *
    852     * @param toDestory The wrapped pooled object to destroy
    853     *
    854     * @throws Exception If the factory fails to destroy the pooled object
    855     *                   cleanly
    856     */
    857    private void destroy(PooledObject<T> toDestory) throws Exception {
    858        toDestory.invalidate();
    859        idleObjects.remove(toDestory);
    860        allObjects.remove(toDestory.getObject());
    861        try {
    862            factory.destroyObject(toDestory);
    863        } finally {
    864            destroyedCount.incrementAndGet();
    865            createCount.decrementAndGet();
    866        }
    867    }
    868
    869    @Override
    870    void ensureMinIdle() throws Exception {
    871        ensureIdle(getMinIdle(), true);
    872    }
    873
    874    /**
    875     * Tries to ensure that {@code idleCount} idle instances exist in the pool.
    876     * <p>
    877     * Creates and adds idle instances until either {@link #getNumIdle()} reaches {@code idleCount}
    878     * or the total number of objects (idle, checked out, or being created) reaches
    879     * {@link #getMaxTotal()}. If {@code always} is false, no instances are created unless
    880     * there are threads waiting to check out instances from the pool.
    881     *
    882     * @param idleCount the number of idle instances desired
    883     * @param always true means create instances even if the pool has no threads waiting
    884     * @throws Exception if the factory's makeObject throws
    885     */
    886    private void ensureIdle(int idleCount, boolean always) throws Exception {
    887        if (idleCount < 1 || isClosed() || (!always && !idleObjects.hasTakeWaiters())) {
    888            return;
    889        }
    890
    891        while (idleObjects.size() < idleCount) {
    892            PooledObject<T> p = create();
    893            if (p == null) {
    894                // Can't create objects, no reason to think another call to
    895                // create will work. Give up.
    896                break;
    897            }
    898            if (getLifo()) {
    899                idleObjects.addFirst(p);
    900            } else {
    901                idleObjects.addLast(p);
    902            }
    903        }
    904    }
    905
    906    /**
    907     * Create an object, and place it into the pool. addObject() is useful for
    908     * "pre-loading" a pool with idle objects.
    909     */
    910    @Override
    911    public void addObject() throws Exception {
    912        assertOpen();
    913        if (factory == null) {
    914            throw new IllegalStateException(
    915                    "Cannot add objects without a factory.");
    916        }
    917        PooledObject<T> p = create();
    918        addIdleObject(p);
    919    }
    920
    921    /**
    922     * Add the provided wrapped pooled object to the set of idle objects for
    923     * this pool. The object must already be part of the pool.
    924     *
    925     * @param p The object to make idle
    926     *
    927     * @throws Exception If the factory fails to passivate the object
    928     */
    929    private void addIdleObject(PooledObject<T> p) throws Exception {
    930        if (p != null) {
    931            factory.passivateObject(p);
    932            if (getLifo()) {
    933                idleObjects.addFirst(p);
    934            } else {
    935                idleObjects.addLast(p);
    936            }
    937        }
    938    }
    939
    940    /**
    941     * Calculate the number of objects to test in a run of the idle object
    942     * evictor.
    943     *
    944     * @return The number of objects to test for validity
    945     */
    946    private int getNumTests() {
    947        int numTestsPerEvictionRun = getNumTestsPerEvictionRun();
    948        if (numTestsPerEvictionRun >= 0) {
    949            return Math.min(numTestsPerEvictionRun, idleObjects.size());
    950        } else {
    951            return (int) (Math.ceil(idleObjects.size() /
    952                    Math.abs((double) numTestsPerEvictionRun)));
    953        }
    954    }
    955
    956    /**
    957     * Recover abandoned objects which have been checked out but
    958     * not used since longer than the removeAbandonedTimeout.
    959     *
    960     * @param ac The configuration to use to identify abandoned objects
    961     */
    962    private void removeAbandoned(AbandonedConfig ac) {
    963        // Generate a list of abandoned objects to remove
    964        final long now = System.currentTimeMillis();
    965        final long timeout =
    966                now - (ac.getRemoveAbandonedTimeout() * 1000L);
    967        ArrayList<PooledObject<T>> remove = new ArrayList<PooledObject<T>>();
    968        Iterator<PooledObject<T>> it = allObjects.values().iterator();
    969        while (it.hasNext()) {
    970            PooledObject<T> pooledObject = it.next();
    971            synchronized (pooledObject) {
    972                if (pooledObject.getState() == PooledObjectState.ALLOCATED &&
    973                        pooledObject.getLastUsedTime() <= timeout) {
    974                    pooledObject.markAbandoned();
    975                    remove.add(pooledObject);
    976                }
    977            }
    978        }
    979
    980        // Now remove the abandoned objects
    981        Iterator<PooledObject<T>> itr = remove.iterator();
    982        while (itr.hasNext()) {
    983            PooledObject<T> pooledObject = itr.next();
    984            if (ac.getLogAbandoned()) {
    985                pooledObject.printStackTrace(ac.getLogWriter());
    986            }
    987            try {
    988                invalidateObject(pooledObject.getObject());
    989            } catch (Exception e) {
    990                e.printStackTrace();
    991            }
    992        }
    993    }
    994
    995
    996    //--- Usage tracking support -----------------------------------------------
    997
    998    @Override
    999    public void use(T pooledObject) {
    1000        AbandonedConfig ac = this.abandonedConfig;
    1001        if (ac != null && ac.getUseUsageTracking()) {
    1002            PooledObject<T> wrapper = allObjects.get(pooledObject);
    1003            wrapper.use();
    1004        }
    1005    }
    1006
    1007
    1008    //--- JMX support ----------------------------------------------------------
    1009
    1010    private volatile String factoryType = null;
    1011
    1012    /**
    1013     * Return an estimate of the number of threads currently blocked waiting for
    1014     * an object from the pool. This is intended for monitoring only, not for
    1015     * synchronization control.
    1016     *
    1017     * @return The estimate of the number of threads currently blocked waiting
    1018     *         for an object from the pool
    1019     */
    1020    @Override
    1021    public int getNumWaiters() {
    1022        if (getBlockWhenExhausted()) {
    1023            return idleObjects.getTakeQueueLength();
    1024        } else {
    1025            return 0;
    1026        }
    1027    }
    1028
    1029    /**
    1030     * Return the type - including the specific type rather than the generic -
    1031     * of the factory.
    1032     *
    1033     * @return A string representation of the factory type
    1034     */
    1035    @Override
    1036    public String getFactoryType() {
    1037        // Not thread safe. Accept that there may be multiple evaluations.
    1038        if (factoryType == null) {
    1039            StringBuilder result = new StringBuilder();
    1040            result.append(factory.getClass().getName());
    1041            result.append('<');
    1042            Class<?> pooledObjectType =
    1043                    PoolImplUtils.getFactoryType(factory.getClass());
    1044            result.append(pooledObjectType.getName());
    1045            result.append('>');
    1046            factoryType = result.toString();
    1047        }
    1048        return factoryType;
    1049    }
    1050
    1051    /**
    1052     * Provides information on all the objects in the pool, both idle (waiting
    1053     * to be borrowed) and active (currently borrowed).
    1054     * <p>
    1055     * Note: This is named listAllObjects so it is presented as an operation via
    1056     * JMX. That means it won't be invoked unless the explicitly requested
    1057     * whereas all attributes will be automatically requested when viewing the
    1058     * attributes for an object in a tool like JConsole.
    1059     *
    1060     * @return Information grouped on all the objects in the pool
    1061     */
    1062    @Override
    1063    public Set<DefaultPooledObjectInfo> listAllObjects() {
    1064        Set<DefaultPooledObjectInfo> result =
    1065                new HashSet<DefaultPooledObjectInfo>(allObjects.size());
    1066        for (PooledObject<T> p : allObjects.values()) {
    1067            result.add(new DefaultPooledObjectInfo(p));
    1068        }
    1069        return result;
    1070    }
    1071
    1072    // --- configuration attributes --------------------------------------------
    1073
    1074    private volatile int maxIdle = GenericObjectPoolConfig.DEFAULT_MAX_IDLE;
    1075    private volatile int minIdle = GenericObjectPoolConfig.DEFAULT_MIN_IDLE;
    1076    private final PooledObjectFactory<T> factory;
    1077
    1078
    1079    // --- internal attributes -------------------------------------------------
    1080
    1081    /*
    1082     * All of the objects currently associated with this pool in any state. It
    1083     * excludes objects that have been destroyed. The size of
    1084     * {@link #allObjects} will always be less than or equal to {@link
    1085     * #_maxActive}. Map keys are pooled objects, values are the PooledObject
    1086     * wrappers used internally by the pool.
    1087     */
    1088    private final Map<T, PooledObject<T>> allObjects =
    1089        new ConcurrentHashMap<T, PooledObject<T>>();
    1090    /*
    1091     * The combined count of the currently created objects and those in the
    1092     * process of being created. Under load, it may exceed {@link #_maxActive}
    1093     * if multiple threads try and create a new object at the same time but
    1094     * {@link #create()} will ensure that there are never more than
    1095     * {@link #_maxActive} objects created at any one time.
    1096     */
    1097    private final AtomicLong createCount = new AtomicLong(0);
    1098    private final LinkedBlockingDeque<PooledObject<T>> idleObjects =
    1099        new LinkedBlockingDeque<PooledObject<T>>();
    1100
    1101    // JMX specific attributes
    1102    private static final String ONAME_BASE =
    1103        "org.apache.commons.pool2:type=GenericObjectPool,name=";
    1104
    1105    // Additional configuration properties for abandoned object tracking
    1106    private volatile AbandonedConfig abandonedConfig = null;
    1107}