Source code

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