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