    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.io.PrintWriter;
    020import java.io.StringWriter;
    021import java.io.Writer;
    022import java.lang.management.ManagementFactory;
    023import java.lang.ref.WeakReference;
    024import java.lang.reflect.InvocationTargetException;
    025import java.time.Duration;
    026import java.time.Instant;
    027import java.util.ArrayList;
    028import java.util.Arrays;
    029import java.util.Deque;
    030import java.util.Iterator;
    031import java.util.List;
    032import java.util.Map;
    033import java.util.TimerTask;
    034import java.util.concurrent.ScheduledFuture;
    035import java.util.concurrent.atomic.AtomicLong;
    036import java.util.stream.Collectors;
    037
    038import javax.management.InstanceAlreadyExistsException;
    039import javax.management.InstanceNotFoundException;
    040import javax.management.MBeanRegistrationException;
    041import javax.management.MBeanServer;
    042import javax.management.MalformedObjectNameException;
    043import javax.management.NotCompliantMBeanException;
    044import javax.management.ObjectName;
    045
    046import org.apache.commons.pool2.BaseObject;
    047import org.apache.commons.pool2.PooledObject;
    048import org.apache.commons.pool2.PooledObjectState;
    049import org.apache.commons.pool2.SwallowedExceptionListener;
    050
    051/**
    052 * Base class that provides common functionality for {@link GenericObjectPool}
    053 * and {@link GenericKeyedObjectPool}. The primary reason this class exists is
    054 * reduce code duplication between the two pool implementations.
    055 *
    056 * @param <T> Type of element pooled in this pool.
    057 *
    058 * This class is intended to be thread-safe.
    059 *
    060 * @since 2.0
    061 */
    062public abstract class BaseGenericObjectPool<T> extends BaseObject {
    063
    064    /**
    065     * The idle object eviction iterator. Holds a reference to the idle objects.
    066     */
    067    class EvictionIterator implements Iterator<PooledObject<T>> {
    068
    069        private final Deque<PooledObject<T>> idleObjects;
    070        private final Iterator<PooledObject<T>> idleObjectIterator;
    071
    072        /**
    073         * Constructs an EvictionIterator for the provided idle instance deque.
    074         * @param idleObjects underlying deque.
    075         */
    076        EvictionIterator(final Deque<PooledObject<T>> idleObjects) {
    077            this.idleObjects = idleObjects;
    078
    079            if (getLifo()) {
    080                idleObjectIterator = idleObjects.descendingIterator();
    081            } else {
    082                idleObjectIterator = idleObjects.iterator();
    083            }
    084        }
    085
    086        /**
    087         * Gets the idle object deque referenced by this iterator.
    088         * @return the idle object deque
    089         */
    090        public Deque<PooledObject<T>> getIdleObjects() {
    091            return idleObjects;
    092        }
    093
    094        /** {@inheritDoc} */
    095        @Override
    096        public boolean hasNext() {
    097            return idleObjectIterator.hasNext();
    098        }
    099
    100        /** {@inheritDoc} */
    101        @Override
    102        public PooledObject<T> next() {
    103            return idleObjectIterator.next();
    104        }
    105
    106        /** {@inheritDoc} */
    107        @Override
    108        public void remove() {
    109            idleObjectIterator.remove();
    110        }
    111
    112    }
    113
    114    /**
    115     * The idle object evictor {@link TimerTask}.
    116     *
    117     * @see GenericKeyedObjectPool#setTimeBetweenEvictionRunsMillis
    118     */
    119    class Evictor implements Runnable {
    120
    121        private ScheduledFuture<?> scheduledFuture;
    122
    123        /**
    124         * Cancels the scheduled future.
    125         */
    126        void cancel() {
    127            scheduledFuture.cancel(false);
    128        }
    129
    130
    131        /**
    132         * Run pool maintenance.  Evict objects qualifying for eviction and then
    133         * ensure that the minimum number of idle instances are available.
    134         * Since the Timer that invokes Evictors is shared for all Pools but
    135         * pools may exist in different class loaders, the Evictor ensures that
    136         * any actions taken are under the class loader of the factory
    137         * associated with the pool.
    138         */
    139        @Override
    140        public void run() {
    141            final ClassLoader savedClassLoader =
    142                    Thread.currentThread().getContextClassLoader();
    143            try {
    144                if (factoryClassLoader != null) {
    145                    // Set the class loader for the factory
    146                    final ClassLoader cl = factoryClassLoader.get();
    147                    if (cl == null) {
    148                        // The pool has been dereferenced and the class loader
    149                        // GC'd. Cancel this timer so the pool can be GC'd as
    150                        // well.
    151                        cancel();
    152                        return;
    153                    }
    154                    Thread.currentThread().setContextClassLoader(cl);
    155                }
    156
    157                // Evict from the pool
    158                try {
    159                    evict();
    160                } catch(final Exception e) {
    161                    swallowException(e);
    162                } catch(final OutOfMemoryError oome) {
    163                    // Log problem but give evictor thread a chance to continue
    164                    // in case error is recoverable
    165                    oome.printStackTrace(System.err);
    166                }
    167                // Re-create idle instances.
    168                try {
    169                    ensureMinIdle();
    170                } catch (final Exception e) {
    171                    swallowException(e);
    172                }
    173            } finally {
    174                // Restore the previous CCL
    175                Thread.currentThread().setContextClassLoader(savedClassLoader);
    176            }
    177        }
    178
    179
    180        /**
    181         * Sets the scheduled future.
    182         *
    183         * @param scheduledFuture the scheduled future.
    184         */
    185        void setScheduledFuture(final ScheduledFuture<?> scheduledFuture) {
    186            this.scheduledFuture = scheduledFuture;
    187        }
    188
    189    }
    190
    191    /**
    192     * Wrapper for objects under management by the pool.
    193     *
    194     * GenericObjectPool and GenericKeyedObjectPool maintain references to all
    195     * objects under management using maps keyed on the objects. This wrapper
    196     * class ensures that objects can work as hash keys.
    197     *
    198     * @param <T> type of objects in the pool
    199     */
    200    static class IdentityWrapper<T> {
    201        /** Wrapped object */
    202        private final T instance;
    203
    204        /**
    205         * Constructs a wrapper for an instance.
    206         *
    207         * @param instance object to wrap
    208         */
    209        public IdentityWrapper(final T instance) {
    210            this.instance = instance;
    211        }
    212
    213        @Override
    214        @SuppressWarnings("rawtypes")
    215        public boolean equals(final Object other) {
    216            return other instanceof IdentityWrapper && ((IdentityWrapper) other).instance == instance;
    217        }
    218
    219        /**
    220         * @return the wrapped object
    221         */
    222        public T getObject() {
    223            return instance;
    224        }
    225
    226        @Override
    227        public int hashCode() {
    228            return System.identityHashCode(instance);
    229        }
    230
    231        @Override
    232        public String toString() {
    233            final StringBuilder builder = new StringBuilder();
    234            builder.append("IdentityWrapper [instance=");
    235            builder.append(instance);
    236            builder.append("]");
    237            return builder.toString();
    238        }
    239    }
    240
    241    /**
    242     * Maintains a cache of values for a single metric and reports
    243     * statistics on the cached values.
    244     */
    245    private class StatsStore {
    246
    247        private static final int NULL = -1;
    248        private final AtomicLong[] values;
    249        private final int size;
    250        private int index;
    251
    252        /**
    253         * Constructs a StatsStore with the given cache size.
    254         *
    255         * @param size number of values to maintain in the cache.
    256         */
    257        StatsStore(final int size) {
    258            this.size = size;
    259            values = new AtomicLong[size];
    260            for (int i = 0; i < size; i++) {
    261                values[i] = new AtomicLong(NULL);
    262            }
    263        }
    264
    265        void add(final Duration value) {
    266            add(value.toMillis());
    267        }
    268
    269        /**
    270         * Adds a value to the cache.  If the cache is full, one of the
    271         * existing values is replaced by the new value.
    272         *
    273         * @param value new value to add to the cache.
    274         */
    275        synchronized void add(final long value) {
    276            values[index].set(value);
    277            index++;
    278            if (index == size) {
    279                index = 0;
    280            }
    281        }
    282
    283        /**
    284         * Gets the current values as a List.
    285         *
    286         * @return the current values as a List.
    287         */
    288        synchronized List<AtomicLong> getCurrentValues() {
    289            return Arrays.stream(values, 0, index).collect(Collectors.toList());
    290        }
    291
    292        /**
    293         * Gets the mean of the cached values.
    294         *
    295         * @return the mean of the cache, truncated to long
    296         */
    297        public long getMean() {
    298            double result = 0;
    299            int counter = 0;
    300            for (int i = 0; i < size; i++) {
    301                final long value = values[i].get();
    302                if (value != NULL) {
    303                    counter++;
    304                    result = result * ((counter - 1) / (double) counter) + value / (double) counter;
    305                }
    306            }
    307            return (long) result;
    308        }
    309
    310        @Override
    311        public String toString() {
    312            final StringBuilder builder = new StringBuilder();
    313            builder.append("StatsStore [");
    314            // Only append what's been filled in.
    315            builder.append(getCurrentValues());
    316            builder.append("], size=");
    317            builder.append(size);
    318            builder.append(", index=");
    319            builder.append(index);
    320            builder.append("]");
    321            return builder.toString();
    322        }
    323
    324    }
    325
    326    // Constants
    327    /**
    328     * The size of the caches used to store historical data for some attributes
    329     * so that rolling means may be calculated.
    330     */
    331    public static final int MEAN_TIMING_STATS_CACHE_SIZE = 100;
    332    private static final String EVICTION_POLICY_TYPE_NAME = EvictionPolicy.class.getName();
    333    private static final Duration DEFAULT_REMOVE_ABANDONED_TIMEOUT = Duration.ofSeconds(Integer.MAX_VALUE);
    334    // Configuration attributes
    335    private volatile int maxTotal = GenericKeyedObjectPoolConfig.DEFAULT_MAX_TOTAL;
    336    private volatile boolean blockWhenExhausted = BaseObjectPoolConfig.DEFAULT_BLOCK_WHEN_EXHAUSTED;
    337    private volatile Duration maxWaitDuration = BaseObjectPoolConfig.DEFAULT_MAX_WAIT;
    338    private volatile boolean lifo = BaseObjectPoolConfig.DEFAULT_LIFO;
    339    private final boolean fairness;
    340    private volatile boolean testOnCreate = BaseObjectPoolConfig.DEFAULT_TEST_ON_CREATE;
    341    private volatile boolean testOnBorrow = BaseObjectPoolConfig.DEFAULT_TEST_ON_BORROW;
    342    private volatile boolean testOnReturn = BaseObjectPoolConfig.DEFAULT_TEST_ON_RETURN;
    343    private volatile boolean testWhileIdle = BaseObjectPoolConfig.DEFAULT_TEST_WHILE_IDLE;
    344    private volatile Duration durationBetweenEvictionRuns = BaseObjectPoolConfig.DEFAULT_TIME_BETWEEN_EVICTION_RUNS;
    345    private volatile int numTestsPerEvictionRun = BaseObjectPoolConfig.DEFAULT_NUM_TESTS_PER_EVICTION_RUN;
    346
    347    private volatile Duration minEvictableIdleDuration = BaseObjectPoolConfig.DEFAULT_MIN_EVICTABLE_IDLE_DURATION;
    348    private volatile Duration softMinEvictableIdleDuration = BaseObjectPoolConfig.DEFAULT_SOFT_MIN_EVICTABLE_IDLE_DURATION;
    349    private volatile EvictionPolicy<T> evictionPolicy;
    350    private volatile Duration evictorShutdownTimeoutDuration = BaseObjectPoolConfig.DEFAULT_EVICTOR_SHUTDOWN_TIMEOUT;
    351    // Internal (primarily state) attributes
    352    final Object closeLock = new Object();
    353    volatile boolean closed;
    354
    355    final Object evictionLock = new Object();
    356    private Evictor evictor; // @GuardedBy("evictionLock")
    357    EvictionIterator evictionIterator; // @GuardedBy("evictionLock")
    358
    359    /*
    360     * Class loader for evictor thread to use since, in a JavaEE or similar
    361     * environment, the context class loader for the evictor thread may not have
    362     * visibility of the correct factory. See POOL-161. Uses a weak reference to
    363     * avoid potential memory leaks if the Pool is discarded rather than closed.
    364     */
    365    private final WeakReference<ClassLoader> factoryClassLoader;
    366    // Monitoring (primarily JMX) attributes
    367    private final ObjectName objectName;
    368    private final String creationStackTrace;
    369    private final AtomicLong borrowedCount = new AtomicLong();
    370    private final AtomicLong returnedCount = new AtomicLong();
    371    final AtomicLong createdCount = new AtomicLong();
    372    final AtomicLong destroyedCount = new AtomicLong();
    373    final AtomicLong destroyedByEvictorCount = new AtomicLong();
    374    final AtomicLong destroyedByBorrowValidationCount = new AtomicLong();
    375
    376    private final StatsStore activeTimes = new StatsStore(MEAN_TIMING_STATS_CACHE_SIZE);
    377    private final StatsStore idleTimes = new StatsStore(MEAN_TIMING_STATS_CACHE_SIZE);
    378    private final StatsStore waitTimes = new StatsStore(MEAN_TIMING_STATS_CACHE_SIZE);
    379
    380    private final AtomicLong maxBorrowWaitTimeMillis = new AtomicLong();
    381
    382    private volatile SwallowedExceptionListener swallowedExceptionListener;
    383    private volatile boolean messageStatistics;
    384
    385    /** Additional configuration properties for abandoned object tracking. */
    386    protected volatile AbandonedConfig abandonedConfig;
    387
    388    /**
    389     * Handles JMX registration (if required) and the initialization required for
    390     * monitoring.
    391     *
    392     * @param config        Pool configuration
    393     * @param jmxNameBase   The default base JMX name for the new pool unless
    394     *                      overridden by the config
    395     * @param jmxNamePrefix Prefix to be used for JMX name for the new pool
    396     */
    397    public BaseGenericObjectPool(final BaseObjectPoolConfig<T> config,
    398            final String jmxNameBase, final String jmxNamePrefix) {
    399        if (config.getJmxEnabled()) {
    400            this.objectName = jmxRegister(config, jmxNameBase, jmxNamePrefix);
    401        } else {
    402            this.objectName = null;
    403        }
    404
    405        // Populate the creation stack trace
    406        this.creationStackTrace = getStackTrace(new Exception());
    407
    408        // save the current TCCL (if any) to be used later by the evictor Thread
    409        final ClassLoader cl = Thread.currentThread().getContextClassLoader();
    410        if (cl == null) {
    411            factoryClassLoader = null;
    412        } else {
    413            factoryClassLoader = new WeakReference<>(cl);
    414        }
    415
    416        fairness = config.getFairness();
    417    }
    418
    419    /**
    420     * Appends statistics if enabled.
    421     * <p>
    422     * Statistics may not accurately reflect snapshot state at the time of the exception because we do not want to lock the pool when gathering this
    423     * information.
    424     * </p>
    425     *
    426     * @param string The root string.
    427     * @return The root string plus statistics.
    428     */
    429    String appendStats(final String string) {
    430        return messageStatistics ? string + ", " + getStatsString() : string;
    431    }
    432
    433    /**
    434     * Verifies that the pool is open.
    435     * @throws IllegalStateException if the pool is closed.
    436     */
    437    final void assertOpen() throws IllegalStateException {
    438        if (isClosed()) {
    439            throw new IllegalStateException("Pool not open");
    440        }
    441    }
    442
    443    /**
    444     * Closes the pool, destroys the remaining idle objects and, if registered
    445     * in JMX, deregisters it.
    446     */
    447    public abstract void close();
    448
    449    /**
    450     * Creates a list of pooled objects to remove based on their state.
    451     * @param abandonedConfig The abandoned configuration.
    452     * @param allObjects PooledObject instances to consider.
    453     * @return a list of pooled objects to remove based on their state.
    454     */
    455    ArrayList<PooledObject<T>> createRemoveList(final AbandonedConfig abandonedConfig, final Map<IdentityWrapper<T>, PooledObject<T>> allObjects) {
    456        final Instant timeout = Instant.now().minus(abandonedConfig.getRemoveAbandonedTimeoutDuration());
    457        final ArrayList<PooledObject<T>> remove = new ArrayList<>();
    458        allObjects.values().forEach(pooledObject -> {
    459            synchronized (pooledObject) {
    460                if (pooledObject.getState() == PooledObjectState.ALLOCATED &&
    461                        pooledObject.getLastUsedInstant().compareTo(timeout) <= 0) {
    462                    pooledObject.markAbandoned();
    463                    remove.add(pooledObject);
    464                }
    465            }
    466        });
    467        return remove;
    468    }
    469
    470    /**
    471     * Tries to ensure that the configured minimum number of idle instances are
    472     * available in the pool.
    473     * @throws Exception if an error occurs creating idle instances
    474     */
    475    abstract void ensureMinIdle() throws Exception;
    476
    477    /**
    478     * Perform {@code numTests} idle object eviction tests, evicting
    479     * examined objects that meet the criteria for eviction. If
    480     * {@code testWhileIdle} is true, examined objects are validated
    481     * when visited (and removed if invalid); otherwise only objects that
    482     * have been idle for more than {@code minEvicableIdleTimeMillis}
    483     * are removed.
    484     *
    485     * @throws Exception when there is a problem evicting idle objects.
    486     */
    487    public abstract void evict() throws Exception;
    488
    489    /**
    490     * Gets whether to block when the {@code borrowObject()} method is
    491     * invoked when the pool is exhausted (the maximum number of "active"
    492     * objects has been reached).
    493     *
    494     * @return {@code true} if {@code borrowObject()} should block
    495     *         when the pool is exhausted
    496     *
    497     * @see #setBlockWhenExhausted
    498     */
    499    public final boolean getBlockWhenExhausted() {
    500        return blockWhenExhausted;
    501    }
    502
    503    /**
    504     * The total number of objects successfully borrowed from this pool over the
    505     * lifetime of the pool.
    506     * @return the borrowed object count
    507     */
    508    public final long getBorrowedCount() {
    509        return borrowedCount.get();
    510    }
    511
    512    /**
    513     * The total number of objects created for this pool over the lifetime of
    514     * the pool.
    515     * @return the created object count
    516     */
    517    public final long getCreatedCount() {
    518        return createdCount.get();
    519    }
    520
    521    /**
    522     * Provides the stack trace for the call that created this pool. JMX
    523     * registration may trigger a memory leak so it is important that pools are
    524     * deregistered when no longer used by calling the {@link #close()} method.
    525     * This method is provided to assist with identifying code that creates but
    526     * does not close it thereby creating a memory leak.
    527     * @return pool creation stack trace
    528     */
    529    public final String getCreationStackTrace() {
    530        return creationStackTrace;
    531    }
    532
    533    /**
    534     * The total number of objects destroyed by this pool as a result of failing
    535     * validation during {@code borrowObject()} over the lifetime of the
    536     * pool.
    537     * @return validation destroyed object count
    538     */
    539    public final long getDestroyedByBorrowValidationCount() {
    540        return destroyedByBorrowValidationCount.get();
    541    }
    542
    543    /**
    544     * The total number of objects destroyed by the evictor associated with this
    545     * pool over the lifetime of the pool.
    546     * @return the evictor destroyed object count
    547     */
    548    public final long getDestroyedByEvictorCount() {
    549        return destroyedByEvictorCount.get();
    550    }
    551
    552    /**
    553     * The total number of objects destroyed by this pool over the lifetime of
    554     * the pool.
    555     * @return the destroyed object count
    556     */
    557    public final long getDestroyedCount() {
    558        return destroyedCount.get();
    559    }
    560
    561    /**
    562     * Gets the {@link EvictionPolicy} defined for this pool.
    563     *
    564     * @return the eviction policy
    565     * @since 2.4
    566     * @since 2.6.0 Changed access from protected to public.
    567     */
    568    public EvictionPolicy<T> getEvictionPolicy() {
    569        return evictionPolicy;
    570    }
    571
    572    /**
    573     * Gets the name of the {@link EvictionPolicy} implementation that is
    574     * used by this pool.
    575     *
    576     * @return  The fully qualified class name of the {@link EvictionPolicy}
    577     *
    578     * @see #setEvictionPolicyClassName(String)
    579     */
    580    public final String getEvictionPolicyClassName() {
    581        return evictionPolicy.getClass().getName();
    582    }
    583
    584    /**
    585     * Gets the timeout that will be used when waiting for the Evictor to
    586     * shutdown if this pool is closed and it is the only pool still using the
    587     * the value for the Evictor.
    588     *
    589     * @return  The timeout that will be used while waiting for
    590     *          the Evictor to shut down.
    591     * @since 2.10.0
    592     * @deprecated Use {@link #getEvictorShutdownTimeoutDuration()}.
    593     */
    594    @Deprecated
    595    public final Duration getEvictorShutdownTimeout() {
    596        return evictorShutdownTimeoutDuration;
    597    }
    598
    599    /**
    600     * Gets the timeout that will be used when waiting for the Evictor to
    601     * shutdown if this pool is closed and it is the only pool still using the
    602     * the value for the Evictor.
    603     *
    604     * @return  The timeout that will be used while waiting for
    605     *          the Evictor to shut down.
    606     * @since 2.11.0
    607     */
    608    public final Duration getEvictorShutdownTimeoutDuration() {
    609        return evictorShutdownTimeoutDuration;
    610    }
    611
    612    /**
    613     * Gets the timeout that will be used when waiting for the Evictor to
    614     * shutdown if this pool is closed and it is the only pool still using the
    615     * the value for the Evictor.
    616     *
    617     * @return  The timeout in milliseconds that will be used while waiting for
    618     *          the Evictor to shut down.
    619     * @deprecated Use {@link #getEvictorShutdownTimeoutDuration()}.
    620     */
    621    @Deprecated
    622    public final long getEvictorShutdownTimeoutMillis() {
    623        return evictorShutdownTimeoutDuration.toMillis();
    624    }
    625
    626    /**
    627     * Gets whether or not the pool serves threads waiting to borrow objects fairly.
    628     * True means that waiting threads are served as if waiting in a FIFO queue.
    629     *
    630     * @return {@code true} if waiting threads are to be served
    631     *             by the pool in arrival order
    632     */
    633    public final boolean getFairness() {
    634        return fairness;
    635    }
    636
    637    /**
    638     * Provides the name under which the pool has been registered with the
    639     * platform MBean server or {@code null} if the pool has not been
    640     * registered.
    641     * @return the JMX name
    642     */
    643    public final ObjectName getJmxName() {
    644        return objectName;
    645    }
    646
    647    /**
    648     * Gets whether the pool has LIFO (last in, first out) behavior with
    649     * respect to idle objects - always returning the most recently used object
    650     * from the pool, or as a FIFO (first in, first out) queue, where the pool
    651     * always returns the oldest object in the idle object pool.
    652     *
    653     * @return {@code true} if the pool is configured with LIFO behavior
    654     *         or {@code false} if the pool is configured with FIFO
    655     *         behavior
    656     *
    657     * @see #setLifo
    658     */
    659    public final boolean getLifo() {
    660        return lifo;
    661    }
    662
    663    /**
    664     * Gets whether this pool identifies and logs any abandoned objects.
    665     *
    666     * @return {@code true} if abandoned object removal is configured for this
    667     *         pool and removal events are to be logged otherwise {@code false}
    668     *
    669     * @see AbandonedConfig#getLogAbandoned()
    670     * @since 2.11.0
    671     */
    672    public boolean getLogAbandoned() {
    673        final AbandonedConfig ac = this.abandonedConfig;
    674        return ac != null && ac.getLogAbandoned();
    675    }
    676
    677    /**
    678     * Gets the maximum time a thread has waited to borrow objects from the pool.
    679     * @return maximum wait time in milliseconds since the pool was created
    680     */
    681    public final long getMaxBorrowWaitTimeMillis() {
    682        return maxBorrowWaitTimeMillis.get();
    683    }
    684
    685    /**
    686     * Gets the maximum number of objects that can be allocated by the pool
    687     * (checked out to clients, or idle awaiting checkout) at a given time. When
    688     * negative, there is no limit to the number of objects that can be
    689     * managed by the pool at one time.
    690     *
    691     * @return the cap on the total number of object instances managed by the
    692     *         pool.
    693     *
    694     * @see #setMaxTotal
    695     */
    696    public final int getMaxTotal() {
    697        return maxTotal;
    698    }
    699
    700    /**
    701     * Gets the maximum duration the
    702     * {@code borrowObject()} method should block before throwing an
    703     * exception when the pool is exhausted and
    704     * {@link #getBlockWhenExhausted} is true. When less than 0, the
    705     * {@code borrowObject()} method may block indefinitely.
    706     *
    707     * @return the maximum number of milliseconds {@code borrowObject()}
    708     *         will block.
    709     *
    710     * @see #setMaxWait
    711     * @see #setBlockWhenExhausted
    712     * @since 2.11.0
    713     */
    714    public final Duration getMaxWaitDuration() {
    715        return maxWaitDuration;
    716    }
    717
    718    /**
    719     * Gets the maximum amount of time (in milliseconds) the
    720     * {@code borrowObject()} method should block before throwing an
    721     * exception when the pool is exhausted and
    722     * {@link #getBlockWhenExhausted} is true. When less than 0, the
    723     * {@code borrowObject()} method may block indefinitely.
    724     *
    725     * @return the maximum number of milliseconds {@code borrowObject()}
    726     *         will block.
    727     *
    728     * @see #setMaxWait
    729     * @see #setBlockWhenExhausted
    730     * @deprecated Use {@link #getMaxWaitDuration()}.
    731     */
    732    @Deprecated
    733    public final long getMaxWaitMillis() {
    734        return maxWaitDuration.toMillis();
    735    }
    736
    737    /**
    738     * The mean time objects are active for based on the last {@link
    739     * #MEAN_TIMING_STATS_CACHE_SIZE} objects returned to the pool.
    740     * @return mean time an object has been checked out from the pool among
    741     * recently returned objects
    742     */
    743    public final long getMeanActiveTimeMillis() {
    744        return activeTimes.getMean();
    745    }
    746
    747    /**
    748     * The mean time threads wait to borrow an object based on the last {@link
    749     * #MEAN_TIMING_STATS_CACHE_SIZE} objects borrowed from the pool.
    750     * @return mean time in milliseconds that a recently served thread has had
    751     * to wait to borrow an object from the pool
    752     */
    753    public final long getMeanBorrowWaitTimeMillis() {
    754        return waitTimes.getMean();
    755    }
    756
    757    /**
    758     * The mean time objects are idle for based on the last {@link
    759     * #MEAN_TIMING_STATS_CACHE_SIZE} objects borrowed from the pool.
    760     * @return mean time an object has been idle in the pool among recently
    761     * borrowed objects
    762     */
    763    public final long getMeanIdleTimeMillis() {
    764        return idleTimes.getMean();
    765    }
    766
    767    /**
    768     * Gets whether to include statistics in exception messages.
    769     * <p>
    770     * Statistics may not accurately reflect snapshot state at the time of the exception because we do not want to lock the pool when gathering this
    771     * information.
    772     * </p>
    773     *
    774     * @return whether to include statistics in exception messages.
    775     * @since 2.11.0
    776     */
    777    public boolean getMessageStatistics() {
    778        return messageStatistics;
    779    }
    780
    781    /**
    782     * Gets the minimum amount of time an object may sit idle in the pool
    783     * before it is eligible for eviction by the idle object evictor (if any -
    784     * see {@link #setTimeBetweenEvictionRuns(Duration)}). When non-positive,
    785     * no objects will be evicted from the pool due to idle time alone.
    786     *
    787     * @return minimum amount of time an object may sit idle in the pool before
    788     *         it is eligible for eviction
    789     *
    790     * @see #setMinEvictableIdleTimeMillis
    791     * @see #setTimeBetweenEvictionRunsMillis
    792     * @since 2.11.0
    793     */
    794    public final Duration getMinEvictableIdleDuration() {
    795        return minEvictableIdleDuration;
    796    }
    797
    798    /**
    799     * Gets the minimum amount of time an object may sit idle in the pool
    800     * before it is eligible for eviction by the idle object evictor (if any -
    801     * see {@link #setTimeBetweenEvictionRuns(Duration)}). When non-positive,
    802     * no objects will be evicted from the pool due to idle time alone.
    803     *
    804     * @return minimum amount of time an object may sit idle in the pool before
    805     *         it is eligible for eviction
    806     *
    807     * @see #setMinEvictableIdleTimeMillis
    808     * @see #setTimeBetweenEvictionRunsMillis
    809     * @since 2.10.0
    810     * @deprecated Use {@link #getMinEvictableIdleDuration()}.
    811     */
    812    @Deprecated
    813    public final Duration getMinEvictableIdleTime() {
    814        return minEvictableIdleDuration;
    815    }
    816
    817    /**
    818     * Gets the minimum amount of time an object may sit idle in the pool
    819     * before it is eligible for eviction by the idle object evictor (if any -
    820     * see {@link #setTimeBetweenEvictionRunsMillis(long)}). When non-positive,
    821     * no objects will be evicted from the pool due to idle time alone.
    822     *
    823     * @return minimum amount of time an object may sit idle in the pool before
    824     *         it is eligible for eviction
    825     *
    826     * @see #setMinEvictableIdleTimeMillis
    827     * @see #setTimeBetweenEvictionRunsMillis
    828     * @deprecated Use {@link #getMinEvictableIdleDuration()}.
    829     */
    830    @Deprecated
    831    public final long getMinEvictableIdleTimeMillis() {
    832        return minEvictableIdleDuration.toMillis();
    833    }
    834
    835    /**
    836     * The number of instances currently idle in this pool.
    837     * @return count of instances available for checkout from the pool
    838     */
    839    public abstract int getNumIdle();
    840
    841    /**
    842     * Gets the maximum number of objects to examine during each run (if any)
    843     * of the idle object evictor thread. When positive, the number of tests
    844     * performed for a run will be the minimum of the configured value and the
    845     * number of idle instances in the pool. When negative, the number of tests
    846     * performed will be <code>ceil({@link #getNumIdle}/
    847     * abs({@link #getNumTestsPerEvictionRun}))</code> which means that when the
    848     * value is {@code -n} roughly one nth of the idle objects will be
    849     * tested per run.
    850     *
    851     * @return max number of objects to examine during each evictor run
    852     *
    853     * @see #setNumTestsPerEvictionRun
    854     * @see #setTimeBetweenEvictionRunsMillis
    855     */
    856    public final int getNumTestsPerEvictionRun() {
    857        return numTestsPerEvictionRun;
    858    }
    859
    860    /**
    861     * Gets whether a check is made for abandoned objects when an object is borrowed
    862     * from this pool.
    863     *
    864     * @return {@code true} if abandoned object removal is configured to be
    865     *         activated by borrowObject otherwise {@code false}
    866     *
    867     * @see AbandonedConfig#getRemoveAbandonedOnBorrow()
    868     * @since 2.11.0
    869     */
    870    public boolean getRemoveAbandonedOnBorrow() {
    871        final AbandonedConfig ac = this.abandonedConfig;
    872        return ac != null && ac.getRemoveAbandonedOnBorrow();
    873    }
    874
    875    /**
    876     * Gets whether a check is made for abandoned objects when the evictor runs.
    877     *
    878     * @return {@code true} if abandoned object removal is configured to be
    879     *         activated when the evictor runs otherwise {@code false}
    880     *
    881     * @see AbandonedConfig#getRemoveAbandonedOnMaintenance()
    882     * @since 2.11.0
    883     */
    884    public boolean getRemoveAbandonedOnMaintenance() {
    885        final AbandonedConfig ac = this.abandonedConfig;
    886        return ac != null && ac.getRemoveAbandonedOnMaintenance();
    887    }
    888
    889    /**
    890     * Gets the timeout before which an object will be considered to be
    891     * abandoned by this pool.
    892     *
    893     * @return The abandoned object timeout in seconds if abandoned object
    894     *         removal is configured for this pool; Integer.MAX_VALUE otherwise.
    895     *
    896     * @see AbandonedConfig#getRemoveAbandonedTimeoutDuration()
    897     * @see AbandonedConfig#getRemoveAbandonedTimeoutDuration()
    898     * @deprecated Use {@link #getRemoveAbandonedTimeoutDuration()}.
    899     * @since 2.11.0
    900     */
    901    @Deprecated
    902    public int getRemoveAbandonedTimeout() {
    903        return (int) getRemoveAbandonedTimeoutDuration().getSeconds();
    904    }
    905
    906    /**
    907     * Gets the timeout before which an object will be considered to be
    908     * abandoned by this pool.
    909     *
    910     * @return The abandoned object timeout in seconds if abandoned object
    911     *         removal is configured for this pool; Integer.MAX_VALUE otherwise.
    912     *
    913     * @see AbandonedConfig#getRemoveAbandonedTimeoutDuration()
    914     * @since 2.11.0
    915     */
    916    public Duration getRemoveAbandonedTimeoutDuration() {
    917        final AbandonedConfig ac = this.abandonedConfig;
    918        return ac != null ? ac.getRemoveAbandonedTimeoutDuration() : DEFAULT_REMOVE_ABANDONED_TIMEOUT;
    919    }
    920
    921    /**
    922     * The total number of objects returned to this pool over the lifetime of
    923     * the pool. This excludes attempts to return the same object multiple
    924     * times.
    925     * @return the returned object count
    926     */
    927    public final long getReturnedCount() {
    928        return returnedCount.get();
    929    }
    930
    931    /**
    932     * Gets the minimum amount of time an object may sit idle in the pool
    933     * before it is eligible for eviction by the idle object evictor (if any -
    934     * see {@link #setTimeBetweenEvictionRuns(Duration)}),
    935     * with the extra condition that at least {@code minIdle} object
    936     * instances remain in the pool. This setting is overridden by
    937     * {@link #getMinEvictableIdleTime} (that is, if
    938     * {@link #getMinEvictableIdleTime} is positive, then
    939     * {@link #getSoftMinEvictableIdleTime} is ignored).
    940     *
    941     * @return minimum amount of time an object may sit idle in the pool before
    942     *         it is eligible for eviction if minIdle instances are available
    943     *
    944     * @see #setSoftMinEvictableIdle(Duration)
    945     * @since 2.11.0
    946     */
    947    public final Duration getSoftMinEvictableIdleDuration() {
    948        return softMinEvictableIdleDuration;
    949    }
    950
    951    /**
    952     * Gets the minimum amount of time an object may sit idle in the pool
    953     * before it is eligible for eviction by the idle object evictor (if any -
    954     * see {@link #setTimeBetweenEvictionRuns(Duration)}),
    955     * with the extra condition that at least {@code minIdle} object
    956     * instances remain in the pool. This setting is overridden by
    957     * {@link #getMinEvictableIdleTime} (that is, if
    958     * {@link #getMinEvictableIdleTime} is positive, then
    959     * {@link #getSoftMinEvictableIdleTime} is ignored).
    960     *
    961     * @return minimum amount of time an object may sit idle in the pool before
    962     *         it is eligible for eviction if minIdle instances are available
    963     *
    964     * @see #setSoftMinEvictableIdle(Duration)
    965     * @since 2.10.0
    966     * @deprecated Use {@link #getSoftMinEvictableIdleDuration}.
    967     */
    968    @Deprecated
    969    public final Duration getSoftMinEvictableIdleTime() {
    970        return softMinEvictableIdleDuration;
    971    }
    972
    973    /**
    974     * Gets the minimum amount of time an object may sit idle in the pool
    975     * before it is eligible for eviction by the idle object evictor (if any -
    976     * see {@link #setTimeBetweenEvictionRunsMillis(long)}),
    977     * with the extra condition that at least {@code minIdle} object
    978     * instances remain in the pool. This setting is overridden by
    979     * {@link #getMinEvictableIdleTimeMillis} (that is, if
    980     * {@link #getMinEvictableIdleTimeMillis} is positive, then
    981     * {@link #getSoftMinEvictableIdleTimeMillis} is ignored).
    982     *
    983     * @return minimum amount of time an object may sit idle in the pool before
    984     *         it is eligible for eviction if minIdle instances are available
    985     *
    986     * @see #setSoftMinEvictableIdleTimeMillis
    987     * @deprecated Use {@link #getSoftMinEvictableIdleTime()}.
    988     */
    989    @Deprecated
    990    public final long getSoftMinEvictableIdleTimeMillis() {
    991        return softMinEvictableIdleDuration.toMillis();
    992    }
    993
    994    /**
    995     * Gets the stack trace of an exception as a string.
    996     * @param e exception to trace
    997     * @return exception stack trace as a string
    998     */
    999    private String getStackTrace(final Exception e) {
    1000        // Need the exception in string form to prevent the retention of
    1001        // references to classes in the stack trace that could trigger a memory
    1002        // leak in a container environment.
    1003        final Writer w = new StringWriter();
    1004        final PrintWriter pw = new PrintWriter(w);
    1005        e.printStackTrace(pw);
    1006        return w.toString();
    1007    }
    1008
    1009    /**
    1010     * Gets a statistics string.
    1011     *
    1012     * @return  a statistics string.
    1013     */
    1014    String getStatsString() {
    1015        // Simply listed in AB order.
    1016        return String.format(
    1017                "activeTimes=%s, blockWhenExhausted=%s, borrowedCount=%,d, closed=%s, createdCount=%,d, destroyedByBorrowValidationCount=%,d, " +
    1018                        "destroyedByEvictorCount=%,d, evictorShutdownTimeoutDuration=%s, fairness=%s, idleTimes=%s, lifo=%s, maxBorrowWaitTimeMillis=%,d, " +
    1019                        "maxTotal=%s, maxWaitDuration=%s, minEvictableIdleDuration=%s, numTestsPerEvictionRun=%s, returnedCount=%s, " +
    1020                        "softMinEvictableIdleDuration=%s, testOnBorrow=%s, testOnCreate=%s, testOnReturn=%s, testWhileIdle=%s, " +
    1021                        "durationBetweenEvictionRuns=%s, waitTimes=%s",
    1022                activeTimes.getCurrentValues(), blockWhenExhausted, borrowedCount.get(), closed, createdCount.get(), destroyedByBorrowValidationCount.get(),
    1023                destroyedByEvictorCount.get(), evictorShutdownTimeoutDuration, fairness, idleTimes.getCurrentValues(), lifo, maxBorrowWaitTimeMillis.get(),
    1024                maxTotal, maxWaitDuration, minEvictableIdleDuration, numTestsPerEvictionRun, returnedCount, softMinEvictableIdleDuration, testOnBorrow,
    1025                testOnCreate, testOnReturn, testWhileIdle, durationBetweenEvictionRuns, waitTimes.getCurrentValues());
    1026    }
    1027
    1028    /**
    1029     * The listener used (if any) to receive notifications of exceptions
    1030     * unavoidably swallowed by the pool.
    1031     *
    1032     * @return The listener or {@code null} for no listener
    1033     */
    1034    public final SwallowedExceptionListener getSwallowedExceptionListener() {
    1035        return swallowedExceptionListener;
    1036    }
    1037
    1038    /**
    1039     * Gets whether objects borrowed from the pool will be validated before
    1040     * being returned from the {@code borrowObject()} method. Validation is
    1041     * performed by the {@code validateObject()} method of the factory
    1042     * associated with the pool. If the object fails to validate, it will be
    1043     * removed from the pool and destroyed, and a new attempt will be made to
    1044     * borrow an object from the pool.
    1045     *
    1046     * @return {@code true} if objects are validated before being returned
    1047     *         from the {@code borrowObject()} method
    1048     *
    1049     * @see #setTestOnBorrow
    1050     */
    1051    public final boolean getTestOnBorrow() {
    1052        return testOnBorrow;
    1053    }
    1054
    1055    /**
    1056     * Gets whether objects created for the pool will be validated before
    1057     * being returned from the {@code borrowObject()} method. Validation is
    1058     * performed by the {@code validateObject()} method of the factory
    1059     * associated with the pool. If the object fails to validate, then
    1060     * {@code borrowObject()} will fail.
    1061     *
    1062     * @return {@code true} if newly created objects are validated before
    1063     *         being returned from the {@code borrowObject()} method
    1064     *
    1065     * @see #setTestOnCreate
    1066     *
    1067     * @since 2.2
    1068     */
    1069    public final boolean getTestOnCreate() {
    1070        return testOnCreate;
    1071    }
    1072
    1073    /**
    1074     * Gets whether objects borrowed from the pool will be validated when
    1075     * they are returned to the pool via the {@code returnObject()} method.
    1076     * Validation is performed by the {@code validateObject()} method of
    1077     * the factory associated with the pool. Returning objects that fail validation
    1078     * are destroyed rather then being returned the pool.
    1079     *
    1080     * @return {@code true} if objects are validated on return to
    1081     *         the pool via the {@code returnObject()} method
    1082     *
    1083     * @see #setTestOnReturn
    1084     */
    1085    public final boolean getTestOnReturn() {
    1086        return testOnReturn;
    1087    }
    1088
    1089    /**
    1090     * Gets whether objects sitting idle in the pool will be validated by the
    1091     * idle object evictor (if any - see
    1092     * {@link #setTimeBetweenEvictionRuns(Duration)}). Validation is performed
    1093     * by the {@code validateObject()} method of the factory associated
    1094     * with the pool. If the object fails to validate, it will be removed from
    1095     * the pool and destroyed.
    1096     *
    1097     * @return {@code true} if objects will be validated by the evictor
    1098     *
    1099     * @see #setTestWhileIdle
    1100     * @see #setTimeBetweenEvictionRunsMillis
    1101     */
    1102    public final boolean getTestWhileIdle() {
    1103        return testWhileIdle;
    1104    }
    1105
    1106    /**
    1107     * Gets the duration to sleep between runs of the idle
    1108     * object evictor thread. When non-positive, no idle object evictor thread
    1109     * will be run.
    1110     *
    1111     * @return number of milliseconds to sleep between evictor runs
    1112     *
    1113     * @see #setTimeBetweenEvictionRuns
    1114     * @since 2.11.0
    1115     */
    1116    public final Duration getDurationBetweenEvictionRuns() {
    1117        return durationBetweenEvictionRuns;
    1118    }
    1119
    1120    /**
    1121     * Gets the duration to sleep between runs of the idle
    1122     * object evictor thread. When non-positive, no idle object evictor thread
    1123     * will be run.
    1124     *
    1125     * @return number of milliseconds to sleep between evictor runs
    1126     *
    1127     * @see #setTimeBetweenEvictionRuns
    1128     * @since 2.10.0
    1129     * @deprecated {@link #getDurationBetweenEvictionRuns()}.
    1130     */
    1131    @Deprecated
    1132    public final Duration getTimeBetweenEvictionRuns() {
    1133        return durationBetweenEvictionRuns;
    1134    }
    1135
    1136    /**
    1137     * Gets the number of milliseconds to sleep between runs of the idle
    1138     * object evictor thread. When non-positive, no idle object evictor thread
    1139     * will be run.
    1140     *
    1141     * @return number of milliseconds to sleep between evictor runs
    1142     *
    1143     * @see #setTimeBetweenEvictionRunsMillis
    1144     * @deprecated Use {@link #getDurationBetweenEvictionRuns()}.
    1145     */
    1146    @Deprecated
    1147    public final long getTimeBetweenEvictionRunsMillis() {
    1148        return durationBetweenEvictionRuns.toMillis();
    1149    }
    1150
    1151    // Monitoring (primarily JMX) related methods
    1152
    1153    /**
    1154     * Gets whether or not abandoned object removal is configured for this pool.
    1155     *
    1156     * @return true if this pool is configured to detect and remove
    1157     * abandoned objects
    1158     * @since 2.11.0
    1159     */
    1160    public boolean isAbandonedConfig() {
    1161        return abandonedConfig != null;
    1162    }
    1163
    1164    /**
    1165     * Has this pool instance been closed.
    1166     * @return {@code true} when this pool has been closed.
    1167     */
    1168    public final boolean isClosed() {
    1169        return closed;
    1170    }
    1171
    1172    /**
    1173     * Registers the pool with the platform MBean server.
    1174     * The registered name will be
    1175     * {@code jmxNameBase + jmxNamePrefix + i} where i is the least
    1176     * integer greater than or equal to 1 such that the name is not already
    1177     * registered. Swallows MBeanRegistrationException, NotCompliantMBeanException
    1178     * returning null.
    1179     *
    1180     * @param config Pool configuration
    1181     * @param jmxNameBase default base JMX name for this pool
    1182     * @param jmxNamePrefix name prefix
    1183     * @return registered ObjectName, null if registration fails
    1184     */
    1185    private ObjectName jmxRegister(final BaseObjectPoolConfig<T> config,
    1186            final String jmxNameBase, String jmxNamePrefix) {
    1187        ObjectName newObjectName = null;
    1188        final MBeanServer mbs = ManagementFactory.getPlatformMBeanServer();
    1189        int i = 1;
    1190        boolean registered = false;
    1191        String base = config.getJmxNameBase();
    1192        if (base == null) {
    1193            base = jmxNameBase;
    1194        }
    1195        while (!registered) {
    1196            try {
    1197                ObjectName objName;
    1198                // Skip the numeric suffix for the first pool in case there is
    1199                // only one so the names are cleaner.
    1200                if (i == 1) {
    1201                    objName = new ObjectName(base + jmxNamePrefix);
    1202                } else {
    1203                    objName = new ObjectName(base + jmxNamePrefix + i);
    1204                }
    1205                mbs.registerMBean(this, objName);
    1206                newObjectName = objName;
    1207                registered = true;
    1208            } catch (final MalformedObjectNameException e) {
    1209                if (BaseObjectPoolConfig.DEFAULT_JMX_NAME_PREFIX.equals(
    1210                        jmxNamePrefix) && jmxNameBase.equals(base)) {
    1211                    // Shouldn't happen. Skip registration if it does.
    1212                    registered = true;
    1213                } else {
    1214                    // Must be an invalid name. Use the defaults instead.
    1215                    jmxNamePrefix =
    1216                            BaseObjectPoolConfig.DEFAULT_JMX_NAME_PREFIX;
    1217                    base = jmxNameBase;
    1218                }
    1219            } catch (final InstanceAlreadyExistsException e) {
    1220                // Increment the index and try again
    1221                i++;
    1222            } catch (final MBeanRegistrationException | NotCompliantMBeanException e) {
    1223                // Shouldn't happen. Skip registration if it does.
    1224                registered = true;
    1225            }
    1226        }
    1227        return newObjectName;
    1228    }
    1229
    1230    /**
    1231     * Unregisters this pool's MBean.
    1232     */
    1233    final void jmxUnregister() {
    1234        if (objectName != null) {
    1235            try {
    1236                ManagementFactory.getPlatformMBeanServer().unregisterMBean(objectName);
    1237            } catch (final MBeanRegistrationException | InstanceNotFoundException e) {
    1238                swallowException(e);
    1239            }
    1240        }
    1241    }
    1242
    1243    /**
    1244     * Marks the object as returning to the pool.
    1245     * @param pooledObject instance to return to the keyed pool
    1246     */
    1247    protected void markReturningState(final PooledObject<T> pooledObject) {
    1248        synchronized (pooledObject) {
    1249            if (pooledObject.getState() != PooledObjectState.ALLOCATED) {
    1250                throw new IllegalStateException("Object has already been returned to this pool or is invalid");
    1251            }
    1252            pooledObject.markReturning(); // Keep from being marked abandoned
    1253        }
    1254    }
    1255
    1256    /**
    1257     * Sets the abandoned object removal configuration.
    1258     *
    1259     * @param abandonedConfig the new configuration to use. This is used by value.
    1260     *
    1261     * @see AbandonedConfig
    1262     * @since 2.11.0
    1263     */
    1264    public void setAbandonedConfig(final AbandonedConfig abandonedConfig) {
    1265        this.abandonedConfig = AbandonedConfig.copy(abandonedConfig);
    1266    }
    1267
    1268    /**
    1269     * Sets whether to block when the {@code borrowObject()} method is
    1270     * invoked when the pool is exhausted (the maximum number of "active"
    1271     * objects has been reached).
    1272     *
    1273     * @param blockWhenExhausted    {@code true} if
    1274     *                              {@code borrowObject()} should block
    1275     *                              when the pool is exhausted
    1276     *
    1277     * @see #getBlockWhenExhausted
    1278     */
    1279    public final void setBlockWhenExhausted(final boolean blockWhenExhausted) {
    1280        this.blockWhenExhausted = blockWhenExhausted;
    1281    }
    1282
    1283    /**
    1284     * Initializes the receiver with the given configuration.
    1285     *
    1286     * @param config Initialization source.
    1287     */
    1288    protected void setConfig(final BaseObjectPoolConfig<T> config) {
    1289        setLifo(config.getLifo());
    1290        setMaxWait(config.getMaxWaitDuration());
    1291        setBlockWhenExhausted(config.getBlockWhenExhausted());
    1292        setTestOnCreate(config.getTestOnCreate());
    1293        setTestOnBorrow(config.getTestOnBorrow());
    1294        setTestOnReturn(config.getTestOnReturn());
    1295        setTestWhileIdle(config.getTestWhileIdle());
    1296        setNumTestsPerEvictionRun(config.getNumTestsPerEvictionRun());
    1297        setMinEvictableIdle(config.getMinEvictableIdleDuration());
    1298        setTimeBetweenEvictionRuns(config.getDurationBetweenEvictionRuns());
    1299        setSoftMinEvictableIdle(config.getSoftMinEvictableIdleDuration());
    1300        final EvictionPolicy<T> policy = config.getEvictionPolicy();
    1301        if (policy == null) {
    1302            // Use the class name (pre-2.6.0 compatible)
    1303            setEvictionPolicyClassName(config.getEvictionPolicyClassName());
    1304        } else {
    1305            // Otherwise, use the class (2.6.0 feature)
    1306            setEvictionPolicy(policy);
    1307        }
    1308        setEvictorShutdownTimeout(config.getEvictorShutdownTimeoutDuration());
    1309    }
    1310
    1311    /**
    1312     * Sets the eviction policy for this pool.
    1313     *
    1314     * @param evictionPolicy
    1315     *            the eviction policy for this pool.
    1316     * @since 2.6.0
    1317     */
    1318    public void setEvictionPolicy(final EvictionPolicy<T> evictionPolicy) {
    1319        this.evictionPolicy = evictionPolicy;
    1320    }
    1321
    1322    /**
    1323     * Sets the eviction policy.
    1324     *
    1325     * @param className Eviction policy class name.
    1326     * @param classLoader Load the class from this class loader.
    1327     */
    1328    @SuppressWarnings("unchecked")
    1329    private void setEvictionPolicy(final String className, final ClassLoader classLoader)
    1330            throws ClassNotFoundException, InstantiationException, IllegalAccessException, InvocationTargetException, NoSuchMethodException {
    1331        final Class<?> clazz = Class.forName(className, true, classLoader);
    1332        final Object policy = clazz.getConstructor().newInstance();
    1333        this.evictionPolicy = (EvictionPolicy<T>) policy;
    1334    }
    1335
    1336    /**
    1337     * Sets the name of the {@link EvictionPolicy} implementation that is used by this pool. The Pool will attempt to
    1338     * load the class using the thread context class loader. If that fails, the use the class loader for the
    1339     * {@link EvictionPolicy} interface.
    1340     *
    1341     * @param evictionPolicyClassName
    1342     *            the fully qualified class name of the new eviction policy
    1343     *
    1344     * @see #getEvictionPolicyClassName()
    1345     * @since 2.6.0 If loading the class using the thread context class loader fails, use the class loader for the
    1346     *        {@link EvictionPolicy} interface.
    1347     */
    1348    public final void setEvictionPolicyClassName(final String evictionPolicyClassName) {
    1349        setEvictionPolicyClassName(evictionPolicyClassName, Thread.currentThread().getContextClassLoader());
    1350    }
    1351
    1352    /**
    1353     * Sets the name of the {@link EvictionPolicy} implementation that is used by this pool. The Pool will attempt to
    1354     * load the class using the given class loader. If that fails, use the class loader for the {@link EvictionPolicy}
    1355     * interface.
    1356     *
    1357     * @param evictionPolicyClassName
    1358     *            the fully qualified class name of the new eviction policy
    1359     * @param classLoader
    1360     *            the class loader to load the given {@code evictionPolicyClassName}.
    1361     *
    1362     * @see #getEvictionPolicyClassName()
    1363     * @since 2.6.0 If loading the class using the given class loader fails, use the class loader for the
    1364     *        {@link EvictionPolicy} interface.
    1365     */
    1366    public final void setEvictionPolicyClassName(final String evictionPolicyClassName, final ClassLoader classLoader) {
    1367        // Getting epClass here and now best matches the caller's environment
    1368        final Class<?> epClass = EvictionPolicy.class;
    1369        final ClassLoader epClassLoader = epClass.getClassLoader();
    1370        try {
    1371            try {
    1372                setEvictionPolicy(evictionPolicyClassName, classLoader);
    1373            } catch (final ClassCastException | ClassNotFoundException e) {
    1374                setEvictionPolicy(evictionPolicyClassName, epClassLoader);
    1375            }
    1376        } catch (final ClassCastException e) {
    1377            throw new IllegalArgumentException("Class " + evictionPolicyClassName + " from class loaders [" +
    1378                    classLoader + ", " + epClassLoader + "] do not implement " + EVICTION_POLICY_TYPE_NAME);
    1379        } catch (final ClassNotFoundException | InstantiationException | IllegalAccessException |
    1380                InvocationTargetException | NoSuchMethodException e) {
    1381            throw new IllegalArgumentException(
    1382                    "Unable to create " + EVICTION_POLICY_TYPE_NAME + " instance of type " + evictionPolicyClassName,
    1383                    e);
    1384        }
    1385    }
    1386
    1387    /**
    1388     * Sets the timeout that will be used when waiting for the Evictor to shutdown if this pool is closed and it is the
    1389     * only pool still using the the value for the Evictor.
    1390     *
    1391     * @param evictorShutdownTimeout the timeout in milliseconds that will be used while waiting for the Evictor
    1392     *                                     to shut down.
    1393     * @since 2.10.0
    1394     */
    1395    public final void setEvictorShutdownTimeout(final Duration evictorShutdownTimeout) {
    1396        this.evictorShutdownTimeoutDuration = PoolImplUtils.nonNull(evictorShutdownTimeout, BaseObjectPoolConfig.DEFAULT_EVICTOR_SHUTDOWN_TIMEOUT);
    1397    }
    1398
    1399    /**
    1400     * Sets the timeout that will be used when waiting for the Evictor to shutdown if this pool is closed and it is the
    1401     * only pool still using the the value for the Evictor.
    1402     *
    1403     * @param evictorShutdownTimeoutMillis the timeout in milliseconds that will be used while waiting for the Evictor
    1404     *                                     to shut down.
    1405     * @deprecated Use {@link #setEvictorShutdownTimeout(Duration)}.
    1406     */
    1407    @Deprecated
    1408    public final void setEvictorShutdownTimeoutMillis(final long evictorShutdownTimeoutMillis) {
    1409        setEvictorShutdownTimeout(Duration.ofMillis(evictorShutdownTimeoutMillis));
    1410    }
    1411
    1412    /**
    1413     * Sets whether the pool has LIFO (last in, first out) behavior with
    1414     * respect to idle objects - always returning the most recently used object
    1415     * from the pool, or as a FIFO (first in, first out) queue, where the pool
    1416     * always returns the oldest object in the idle object pool.
    1417     *
    1418     * @param lifo  {@code true} if the pool is to be configured with LIFO
    1419     *              behavior or {@code false} if the pool is to be
    1420     *              configured with FIFO behavior
    1421     *
    1422     * @see #getLifo()
    1423     */
    1424    public final void setLifo(final boolean lifo) {
    1425        this.lifo = lifo;
    1426    }
    1427
    1428    /**
    1429     * Sets the cap on the number of objects that can be allocated by the pool
    1430     * (checked out to clients, or idle awaiting checkout) at a given time. Use
    1431     * a negative value for no limit.
    1432     *
    1433     * @param maxTotal  The cap on the total number of object instances managed
    1434     *                  by the pool. Negative values mean that there is no limit
    1435     *                  to the number of objects allocated by the pool.
    1436     *
    1437     * @see #getMaxTotal
    1438     */
    1439    public final void setMaxTotal(final int maxTotal) {
    1440        this.maxTotal = maxTotal;
    1441    }
    1442
    1443    /**
    1444     * Sets the maximum duration the
    1445     * {@code borrowObject()} method should block before throwing an
    1446     * exception when the pool is exhausted and
    1447     * {@link #getBlockWhenExhausted} is true. When less than 0, the
    1448     * {@code borrowObject()} method may block indefinitely.
    1449     *
    1450     * @param maxWaitDuration the maximum duration
    1451     *                      {@code borrowObject()} will block or negative
    1452     *                      for indefinitely.
    1453     *
    1454     * @see #getMaxWaitDuration
    1455     * @see #setBlockWhenExhausted
    1456     * @since 2.11.0
    1457     */
    1458    public final void setMaxWait(final Duration maxWaitDuration) {
    1459        this.maxWaitDuration = PoolImplUtils.nonNull(maxWaitDuration, BaseObjectPoolConfig.DEFAULT_MAX_WAIT);
    1460    }
    1461
    1462    /**
    1463     * Sets the maximum amount of time (in milliseconds) the
    1464     * {@code borrowObject()} method should block before throwing an
    1465     * exception when the pool is exhausted and
    1466     * {@link #getBlockWhenExhausted} is true. When less than 0, the
    1467     * {@code borrowObject()} method may block indefinitely.
    1468     *
    1469     * @param maxWaitMillis the maximum number of milliseconds
    1470     *                      {@code borrowObject()} will block or negative
    1471     *                      for indefinitely.
    1472     *
    1473     * @see #getMaxWaitDuration
    1474     * @see #setBlockWhenExhausted
    1475     * @deprecated Use {@link #setMaxWait}.
    1476     */
    1477    @Deprecated
    1478    public final void setMaxWaitMillis(final long maxWaitMillis) {
    1479        setMaxWait(Duration.ofMillis(maxWaitMillis));
    1480    }
    1481
    1482    /**
    1483     * Sets whether to include statistics in exception messages.
    1484     * <p>
    1485     * Statistics may not accurately reflect snapshot state at the time of the exception because we do not want to lock the pool when gathering this
    1486     * information.
    1487     * </p>
    1488     *
    1489     * @param messagesDetails whether to include statistics in exception messages.
    1490     * @since 2.11.0
    1491     */
    1492    public void setMessagesStatistics(final boolean messagesDetails) {
    1493        this.messageStatistics = messagesDetails;
    1494    }
    1495
    1496    /**
    1497     * Sets the minimum amount of time an object may sit idle in the pool
    1498     * before it is eligible for eviction by the idle object evictor (if any -
    1499     * see {@link #setTimeBetweenEvictionRuns(Duration)}). When non-positive,
    1500     * no objects will be evicted from the pool due to idle time alone.
    1501     *
    1502     * @param minEvictableIdleTime
    1503     *            minimum amount of time an object may sit idle in the pool
    1504     *            before it is eligible for eviction
    1505     *
    1506     * @see #getMinEvictableIdleTime
    1507     * @see #setTimeBetweenEvictionRuns
    1508     * @since 2.11.0
    1509     */
    1510    public final void setMinEvictableIdle(final Duration minEvictableIdleTime) {
    1511        this.minEvictableIdleDuration = PoolImplUtils.nonNull(minEvictableIdleTime, BaseObjectPoolConfig.DEFAULT_MIN_EVICTABLE_IDLE_DURATION);
    1512    }
    1513
    1514    /**
    1515     * Sets the minimum amount of time an object may sit idle in the pool
    1516     * before it is eligible for eviction by the idle object evictor (if any -
    1517     * see {@link #setTimeBetweenEvictionRuns(Duration)}). When non-positive,
    1518     * no objects will be evicted from the pool due to idle time alone.
    1519     *
    1520     * @param minEvictableIdleTime
    1521     *            minimum amount of time an object may sit idle in the pool
    1522     *            before it is eligible for eviction
    1523     *
    1524     * @see #getMinEvictableIdleTime
    1525     * @see #setTimeBetweenEvictionRuns
    1526     * @since 2.10.0
    1527     * @deprecated Use {@link #setMinEvictableIdle(Duration)}.
    1528     */
    1529    @Deprecated
    1530    public final void setMinEvictableIdleTime(final Duration minEvictableIdleTime) {
    1531        this.minEvictableIdleDuration = PoolImplUtils.nonNull(minEvictableIdleTime, BaseObjectPoolConfig.DEFAULT_MIN_EVICTABLE_IDLE_DURATION);
    1532    }
    1533
    1534    /**
    1535     * Sets the minimum amount of time an object may sit idle in the pool
    1536     * before it is eligible for eviction by the idle object evictor (if any -
    1537     * see {@link #setTimeBetweenEvictionRunsMillis(long)}). When non-positive,
    1538     * no objects will be evicted from the pool due to idle time alone.
    1539     *
    1540     * @param minEvictableIdleTimeMillis
    1541     *            minimum amount of time an object may sit idle in the pool
    1542     *            before it is eligible for eviction
    1543     *
    1544     * @see #getMinEvictableIdleTimeMillis
    1545     * @see #setTimeBetweenEvictionRunsMillis
    1546     * @deprecated Use {@link #setMinEvictableIdleTime(Duration)}.
    1547     */
    1548    @Deprecated
    1549    public final void setMinEvictableIdleTimeMillis(final long minEvictableIdleTimeMillis) {
    1550        setMinEvictableIdleTime(Duration.ofMillis(minEvictableIdleTimeMillis));
    1551    }
    1552
    1553    /**
    1554     * Sets the maximum number of objects to examine during each run (if any)
    1555     * of the idle object evictor thread. When positive, the number of tests
    1556     * performed for a run will be the minimum of the configured value and the
    1557     * number of idle instances in the pool. When negative, the number of tests
    1558     * performed will be <code>ceil({@link #getNumIdle}/
    1559     * abs({@link #getNumTestsPerEvictionRun}))</code> which means that when the
    1560     * value is {@code -n} roughly one nth of the idle objects will be
    1561     * tested per run.
    1562     *
    1563     * @param numTestsPerEvictionRun
    1564     *            max number of objects to examine during each evictor run
    1565     *
    1566     * @see #getNumTestsPerEvictionRun
    1567     * @see #setTimeBetweenEvictionRunsMillis
    1568     */
    1569    public final void setNumTestsPerEvictionRun(final int numTestsPerEvictionRun) {
    1570        this.numTestsPerEvictionRun = numTestsPerEvictionRun;
    1571    }
    1572
    1573    /**
    1574     * Sets the minimum amount of time an object may sit idle in the pool
    1575     * before it is eligible for eviction by the idle object evictor (if any -
    1576     * see {@link #setTimeBetweenEvictionRuns(Duration)}),
    1577     * with the extra condition that at least {@code minIdle} object
    1578     * instances remain in the pool. This setting is overridden by
    1579     * {@link #getMinEvictableIdleTime} (that is, if
    1580     * {@link #getMinEvictableIdleTime} is positive, then
    1581     * {@link #getSoftMinEvictableIdleTime} is ignored).
    1582     *
    1583     * @param softMinEvictableIdleTime
    1584     *            minimum amount of time an object may sit idle in the pool
    1585     *            before it is eligible for eviction if minIdle instances are
    1586     *            available
    1587     *
    1588     * @see #getSoftMinEvictableIdleTimeMillis
    1589     * @since 2.11.0
    1590     */
    1591    public final void setSoftMinEvictableIdle(final Duration softMinEvictableIdleTime) {
    1592        this.softMinEvictableIdleDuration = PoolImplUtils.nonNull(softMinEvictableIdleTime, BaseObjectPoolConfig.DEFAULT_SOFT_MIN_EVICTABLE_IDLE_DURATION);
    1593    }
    1594
    1595    /**
    1596     * Sets the minimum amount of time an object may sit idle in the pool
    1597     * before it is eligible for eviction by the idle object evictor (if any -
    1598     * see {@link #setTimeBetweenEvictionRuns(Duration)}),
    1599     * with the extra condition that at least {@code minIdle} object
    1600     * instances remain in the pool. This setting is overridden by
    1601     * {@link #getMinEvictableIdleTime} (that is, if
    1602     * {@link #getMinEvictableIdleTime} is positive, then
    1603     * {@link #getSoftMinEvictableIdleTime} is ignored).
    1604     *
    1605     * @param softMinEvictableIdleTime
    1606     *            minimum amount of time an object may sit idle in the pool
    1607     *            before it is eligible for eviction if minIdle instances are
    1608     *            available
    1609     *
    1610     * @see #getSoftMinEvictableIdleTimeMillis
    1611     * @since 2.10.0
    1612     * @deprecated Use {@link #setSoftMinEvictableIdle(Duration)}.
    1613     */
    1614    @Deprecated
    1615    public final void setSoftMinEvictableIdleTime(final Duration softMinEvictableIdleTime) {
    1616        this.softMinEvictableIdleDuration = PoolImplUtils.nonNull(softMinEvictableIdleTime, BaseObjectPoolConfig.DEFAULT_SOFT_MIN_EVICTABLE_IDLE_DURATION);
    1617    }
    1618
    1619    /**
    1620     * Sets the minimum amount of time an object may sit idle in the pool
    1621     * before it is eligible for eviction by the idle object evictor (if any -
    1622     * see {@link #setTimeBetweenEvictionRunsMillis(long)}),
    1623     * with the extra condition that at least {@code minIdle} object
    1624     * instances remain in the pool. This setting is overridden by
    1625     * {@link #getMinEvictableIdleTimeMillis} (that is, if
    1626     * {@link #getMinEvictableIdleTimeMillis} is positive, then
    1627     * {@link #getSoftMinEvictableIdleTimeMillis} is ignored).
    1628     *
    1629     * @param softMinEvictableIdleTimeMillis
    1630     *            minimum amount of time an object may sit idle in the pool
    1631     *            before it is eligible for eviction if minIdle instances are
    1632     *            available
    1633     *
    1634     * @see #getSoftMinEvictableIdleTimeMillis
    1635     * @deprecated Use {@link #setSoftMinEvictableIdle(Duration)}.
    1636     */
    1637    @Deprecated
    1638    public final void setSoftMinEvictableIdleTimeMillis(final long softMinEvictableIdleTimeMillis) {
    1639        setSoftMinEvictableIdleTime(Duration.ofMillis(softMinEvictableIdleTimeMillis));
    1640    }
    1641
    1642    /**
    1643     * The listener used (if any) to receive notifications of exceptions
    1644     * unavoidably swallowed by the pool.
    1645     *
    1646     * @param swallowedExceptionListener    The listener or {@code null}
    1647     *                                      for no listener
    1648     */
    1649    public final void setSwallowedExceptionListener(
    1650            final SwallowedExceptionListener swallowedExceptionListener) {
    1651        this.swallowedExceptionListener = swallowedExceptionListener;
    1652    }
    1653
    1654    /**
    1655     * Sets whether objects borrowed from the pool will be validated before
    1656     * being returned from the {@code borrowObject()} method. Validation is
    1657     * performed by the {@code validateObject()} method of the factory
    1658     * associated with the pool. If the object fails to validate, it will be
    1659     * removed from the pool and destroyed, and a new attempt will be made to
    1660     * borrow an object from the pool.
    1661     *
    1662     * @param testOnBorrow  {@code true} if objects should be validated
    1663     *                      before being returned from the
    1664     *                      {@code borrowObject()} method
    1665     *
    1666     * @see #getTestOnBorrow
    1667     */
    1668    public final void setTestOnBorrow(final boolean testOnBorrow) {
    1669        this.testOnBorrow = testOnBorrow;
    1670    }
    1671
    1672    /**
    1673     * Sets whether objects created for the pool will be validated before
    1674     * being returned from the {@code borrowObject()} method. Validation is
    1675     * performed by the {@code validateObject()} method of the factory
    1676     * associated with the pool. If the object fails to validate, then
    1677     * {@code borrowObject()} will fail.
    1678     *
    1679     * @param testOnCreate  {@code true} if newly created objects should be
    1680     *                      validated before being returned from the
    1681     *                      {@code borrowObject()} method
    1682     *
    1683     * @see #getTestOnCreate
    1684     *
    1685     * @since 2.2
    1686     */
    1687    public final void setTestOnCreate(final boolean testOnCreate) {
    1688        this.testOnCreate = testOnCreate;
    1689    }
    1690
    1691    /**
    1692     * Sets whether objects borrowed from the pool will be validated when
    1693     * they are returned to the pool via the {@code returnObject()} method.
    1694     * Validation is performed by the {@code validateObject()} method of
    1695     * the factory associated with the pool. Returning objects that fail validation
    1696     * are destroyed rather then being returned the pool.
    1697     *
    1698     * @param testOnReturn {@code true} if objects are validated on
    1699     *                     return to the pool via the
    1700     *                     {@code returnObject()} method
    1701     *
    1702     * @see #getTestOnReturn
    1703     */
    1704    public final void setTestOnReturn(final boolean testOnReturn) {
    1705        this.testOnReturn = testOnReturn;
    1706    }
    1707
    1708    /**
    1709     * Sets whether objects sitting idle in the pool will be validated by the
    1710     * idle object evictor (if any - see
    1711     * {@link #setTimeBetweenEvictionRuns(Duration)}). Validation is performed
    1712     * by the {@code validateObject()} method of the factory associated
    1713     * with the pool. If the object fails to validate, it will be removed from
    1714     * the pool and destroyed.  Note that setting this property has no effect
    1715     * unless the idle object evictor is enabled by setting
    1716     * {@code timeBetweenEvictionRunsMillis} to a positive value.
    1717     *
    1718     * @param testWhileIdle
    1719     *            {@code true} so objects will be validated by the evictor
    1720     *
    1721     * @see #getTestWhileIdle
    1722     * @see #setTimeBetweenEvictionRuns
    1723     */
    1724    public final void setTestWhileIdle(final boolean testWhileIdle) {
    1725        this.testWhileIdle = testWhileIdle;
    1726    }
    1727
    1728    /**
    1729     * Sets the number of milliseconds to sleep between runs of the idle object evictor thread.
    1730     * <ul>
    1731     * <li>When positive, the idle object evictor thread starts.</li>
    1732     * <li>When non-positive, no idle object evictor thread runs.</li>
    1733     * </ul>
    1734     *
    1735     * @param timeBetweenEvictionRuns
    1736     *            duration to sleep between evictor runs
    1737     *
    1738     * @see #getTimeBetweenEvictionRunsMillis
    1739     * @since 2.10.0
    1740     */
    1741    public final void setTimeBetweenEvictionRuns(final Duration timeBetweenEvictionRuns) {
    1742        this.durationBetweenEvictionRuns = PoolImplUtils.nonNull(timeBetweenEvictionRuns, BaseObjectPoolConfig.DEFAULT_TIME_BETWEEN_EVICTION_RUNS);
    1743        startEvictor(this.durationBetweenEvictionRuns);
    1744    }
    1745
    1746    /**
    1747     * Sets the number of milliseconds to sleep between runs of the idle object evictor thread.
    1748     * <ul>
    1749     * <li>When positive, the idle object evictor thread starts.</li>
    1750     * <li>When non-positive, no idle object evictor thread runs.</li>
    1751     * </ul>
    1752     *
    1753     * @param timeBetweenEvictionRunsMillis
    1754     *            number of milliseconds to sleep between evictor runs
    1755     *
    1756     * @see #getTimeBetweenEvictionRunsMillis
    1757     * @deprecated Use {@link #setTimeBetweenEvictionRuns(Duration)}.
    1758     */
    1759    @Deprecated
    1760    public final void setTimeBetweenEvictionRunsMillis(final long timeBetweenEvictionRunsMillis) {
    1761        setTimeBetweenEvictionRuns(Duration.ofMillis(timeBetweenEvictionRunsMillis));
    1762    }
    1763
    1764    /**
    1765     * <p>Starts the evictor with the given delay. If there is an evictor
    1766     * running when this method is called, it is stopped and replaced with a
    1767     * new evictor with the specified delay.</p>
    1768     *
    1769     * <p>This method needs to be final, since it is called from a constructor.
    1770     * See POOL-195.</p>
    1771     *
    1772     * @param delay time in milliseconds before start and between eviction runs
    1773     */
    1774    final void startEvictor(final Duration delay) {
    1775        synchronized (evictionLock) {
    1776            final boolean isPositiverDelay = PoolImplUtils.isPositive(delay);
    1777            if (evictor == null) { // Starting evictor for the first time or after a cancel
    1778                if (isPositiverDelay) { // Starting new evictor
    1779                    evictor = new Evictor();
    1780                    EvictionTimer.schedule(evictor, delay, delay);
    1781                }
    1782            } else if (isPositiverDelay) { // Stop or restart of existing evictor: Restart
    1783                synchronized (EvictionTimer.class) { // Ensure no cancel can happen between cancel / schedule calls
    1784                    EvictionTimer.cancel(evictor, evictorShutdownTimeoutDuration, true);
    1785                    evictor = null;
    1786                    evictionIterator = null;
    1787                    evictor = new Evictor();
    1788                    EvictionTimer.schedule(evictor, delay, delay);
    1789                }
    1790            } else { // Stopping evictor
    1791                EvictionTimer.cancel(evictor, evictorShutdownTimeoutDuration, false);
    1792            }
    1793        }
    1794    }
    1795
    1796    /**
    1797     * Stops the evictor.
    1798     */
    1799    void stopEvictor() {
    1800        startEvictor(Duration.ofMillis(-1L));
    1801    }
    1802
    1803    /**
    1804     * Swallows an exception and notifies the configured listener for swallowed
    1805     * exceptions queue.
    1806     *
    1807     * @param swallowException exception to be swallowed
    1808     */
    1809    final void swallowException(final Exception swallowException) {
    1810        final SwallowedExceptionListener listener = getSwallowedExceptionListener();
    1811
    1812        if (listener == null) {
    1813            return;
    1814        }
    1815
    1816        try {
    1817            listener.onSwallowException(swallowException);
    1818        } catch (final VirtualMachineError e) {
    1819            throw e;
    1820        } catch (final Throwable t) {
    1821            // Ignore. Enjoy the irony.
    1822        }
    1823    }
    1824
    1825    @Override
    1826    protected void toStringAppendFields(final StringBuilder builder) {
    1827        builder.append("maxTotal=");
    1828        builder.append(maxTotal);
    1829        builder.append(", blockWhenExhausted=");
    1830        builder.append(blockWhenExhausted);
    1831        builder.append(", maxWaitDuration=");
    1832        builder.append(maxWaitDuration);
    1833        builder.append(", lifo=");
    1834        builder.append(lifo);
    1835        builder.append(", fairness=");
    1836        builder.append(fairness);
    1837        builder.append(", testOnCreate=");
    1838        builder.append(testOnCreate);
    1839        builder.append(", testOnBorrow=");
    1840        builder.append(testOnBorrow);
    1841        builder.append(", testOnReturn=");
    1842        builder.append(testOnReturn);
    1843        builder.append(", testWhileIdle=");
    1844        builder.append(testWhileIdle);
    1845        builder.append(", timeBetweenEvictionRunsMillis=");
    1846        builder.append(durationBetweenEvictionRuns);
    1847        builder.append(", numTestsPerEvictionRun=");
    1848        builder.append(numTestsPerEvictionRun);
    1849        builder.append(", minEvictableIdleTimeDuration=");
    1850        builder.append(minEvictableIdleDuration);
    1851        builder.append(", softMinEvictableIdleTimeDuration=");
    1852        builder.append(softMinEvictableIdleDuration);
    1853        builder.append(", evictionPolicy=");
    1854        builder.append(evictionPolicy);
    1855        builder.append(", closeLock=");
    1856        builder.append(closeLock);
    1857        builder.append(", closed=");
    1858        builder.append(closed);
    1859        builder.append(", evictionLock=");
    1860        builder.append(evictionLock);
    1861        builder.append(", evictor=");
    1862        builder.append(evictor);
    1863        builder.append(", evictionIterator=");
    1864        builder.append(evictionIterator);
    1865        builder.append(", factoryClassLoader=");
    1866        builder.append(factoryClassLoader);
    1867        builder.append(", oname=");
    1868        builder.append(objectName);
    1869        builder.append(", creationStackTrace=");
    1870        builder.append(creationStackTrace);
    1871        builder.append(", borrowedCount=");
    1872        builder.append(borrowedCount);
    1873        builder.append(", returnedCount=");
    1874        builder.append(returnedCount);
    1875        builder.append(", createdCount=");
    1876        builder.append(createdCount);
    1877        builder.append(", destroyedCount=");
    1878        builder.append(destroyedCount);
    1879        builder.append(", destroyedByEvictorCount=");
    1880        builder.append(destroyedByEvictorCount);
    1881        builder.append(", destroyedByBorrowValidationCount=");
    1882        builder.append(destroyedByBorrowValidationCount);
    1883        builder.append(", activeTimes=");
    1884        builder.append(activeTimes);
    1885        builder.append(", idleTimes=");
    1886        builder.append(idleTimes);
    1887        builder.append(", waitTimes=");
    1888        builder.append(waitTimes);
    1889        builder.append(", maxBorrowWaitTimeMillis=");
    1890        builder.append(maxBorrowWaitTimeMillis);
    1891        builder.append(", swallowedExceptionListener=");
    1892        builder.append(swallowedExceptionListener);
    1893    }
    1894
    1895    /**
    1896     * Updates statistics after an object is borrowed from the pool.
    1897     *
    1898     * @param p object borrowed from the pool
    1899     * @param waitDuration time (in milliseconds) that the borrowing thread had to wait
    1900     */
    1901    final void updateStatsBorrow(final PooledObject<T> p, final Duration waitDuration) {
    1902        borrowedCount.incrementAndGet();
    1903        idleTimes.add(p.getIdleDuration());
    1904        waitTimes.add(waitDuration);
    1905        final long waitTimeMillis = waitDuration.toMillis();
    1906
    1907        // lock-free optimistic-locking maximum
    1908        long currentMaxMillis;
    1909        do {
    1910            currentMaxMillis = maxBorrowWaitTimeMillis.get();
    1911            if (currentMaxMillis >= waitTimeMillis) {
    1912                break;
    1913            }
    1914        } while (!maxBorrowWaitTimeMillis.compareAndSet(currentMaxMillis, waitTimeMillis));
    1915    }
    1916
    1917    /**
    1918     * Updates statistics after an object is returned to the pool.
    1919     *
    1920     * @param activeTime the amount of time (in milliseconds) that the returning
    1921     * object was checked out
    1922     */
    1923    final void updateStatsReturn(final Duration activeTime) {
    1924        returnedCount.incrementAndGet();
    1925        activeTimes.add(activeTime);
    1926    }
    1927
    1928
    1929}