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