    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    class EvictionIterator implements Iterator<PooledObject<T>> {
    069
    070        private final Deque<PooledObject<T>> idleObjects;
    071        private final Iterator<PooledObject<T>> idleObjectIterator;
    072
    073        /**
    074         * Constructs an EvictionIterator for the provided idle instance deque.
    075         * @param idleObjects underlying deque.
    076         */
    077        EvictionIterator(final Deque<PooledObject<T>> idleObjects) {
    078            this.idleObjects = idleObjects;
    079
    080            if (getLifo()) {
    081                idleObjectIterator = idleObjects.descendingIterator();
    082            } else {
    083                idleObjectIterator = idleObjects.iterator();
    084            }
    085        }
    086
    087        /**
    088         * Gets the idle object deque referenced by this iterator.
    089         * @return the idle object deque
    090         */
    091        public Deque<PooledObject<T>> getIdleObjects() {
    092            return idleObjects;
    093        }
    094
    095        /** {@inheritDoc} */
    096        @Override
    097        public boolean hasNext() {
    098            return idleObjectIterator.hasNext();
    099        }
    100
    101        /** {@inheritDoc} */
    102        @Override
    103        public PooledObject<T> next() {
    104            return idleObjectIterator.next();
    105        }
    106
    107        /** {@inheritDoc} */
    108        @Override
    109        public void remove() {
    110            idleObjectIterator.remove();
    111        }
    112
    113    }
    114
    115    /**
    116     * The idle object evictor {@link TimerTask}.
    117     *
    118     * @see GenericKeyedObjectPool#setTimeBetweenEvictionRunsMillis
    119     */
    120    class Evictor implements Runnable {
    121
    122        private ScheduledFuture<?> scheduledFuture;
    123
    124        /**
    125         * Cancels the scheduled future.
    126         */
    127        void cancel() {
    128            scheduledFuture.cancel(false);
    129        }
    130
    131        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 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     *
    583     * @see #setTimeBetweenEvictionRuns
    584     * @since 2.11.0
    585     */
    586    public final Duration getDurationBetweenEvictionRuns() {
    587        return durationBetweenEvictionRuns;
    588    }
    589
    590    /**
    591     * Gets the {@link EvictionPolicy} defined for this pool.
    592     *
    593     * @return the eviction policy
    594     * @since 2.4
    595     * @since 2.6.0 Changed access from protected to public.
    596     */
    597    public EvictionPolicy<T> getEvictionPolicy() {
    598        return evictionPolicy;
    599    }
    600
    601    /**
    602     * Gets the name of the {@link EvictionPolicy} implementation that is
    603     * used by this pool.
    604     *
    605     * @return  The fully qualified class name of the {@link EvictionPolicy}
    606     *
    607     * @see #setEvictionPolicyClassName(String)
    608     */
    609    public final String getEvictionPolicyClassName() {
    610        return evictionPolicy.getClass().getName();
    611    }
    612
    613    /**
    614     * Gets the timeout that will be used when waiting for the Evictor to
    615     * shutdown if this pool is closed and it is the only pool still using the
    616     * the value for the Evictor.
    617     *
    618     * @return  The timeout that will be used while waiting for
    619     *          the Evictor to shut down.
    620     * @since 2.10.0
    621     * @deprecated Use {@link #getEvictorShutdownTimeoutDuration()}.
    622     */
    623    @Deprecated
    624    public final Duration getEvictorShutdownTimeout() {
    625        return evictorShutdownTimeoutDuration;
    626    }
    627
    628    /**
    629     * Gets the timeout that will be used when waiting for the Evictor to
    630     * shutdown if this pool is closed and it is the only pool still using the
    631     * the value for the Evictor.
    632     *
    633     * @return  The timeout that will be used while waiting for
    634     *          the Evictor to shut down.
    635     * @since 2.11.0
    636     */
    637    public final Duration getEvictorShutdownTimeoutDuration() {
    638        return evictorShutdownTimeoutDuration;
    639    }
    640
    641    /**
    642     * Gets the timeout that will be used when waiting for the Evictor to
    643     * shutdown if this pool is closed and it is the only pool still using the
    644     * the value for the Evictor.
    645     *
    646     * @return  The timeout in milliseconds that will be used while waiting for
    647     *          the Evictor to shut down.
    648     * @deprecated Use {@link #getEvictorShutdownTimeoutDuration()}.
    649     */
    650    @Deprecated
    651    public final long getEvictorShutdownTimeoutMillis() {
    652        return evictorShutdownTimeoutDuration.toMillis();
    653    }
    654
    655    /**
    656     * Gets whether or not the pool serves threads waiting to borrow objects fairly.
    657     * True means that waiting threads are served as if waiting in a FIFO queue.
    658     *
    659     * @return {@code true} if waiting threads are to be served
    660     *             by the pool in arrival order
    661     */
    662    public final boolean getFairness() {
    663        return fairness;
    664    }
    665
    666    /**
    667     * Gets the name under which the pool has been registered with the
    668     * platform MBean server or {@code null} if the pool has not been
    669     * registered.
    670     * @return the JMX name
    671     */
    672    public final ObjectName getJmxName() {
    673        return objectName;
    674    }
    675
    676    /**
    677     * Gets whether the pool has LIFO (last in, first out) behavior with
    678     * respect to idle objects - always returning the most recently used object
    679     * from the pool, or as a FIFO (first in, first out) queue, where the pool
    680     * always returns the oldest object in the idle object pool.
    681     *
    682     * @return {@code true} if the pool is configured with LIFO behavior
    683     *         or {@code false} if the pool is configured with FIFO
    684     *         behavior
    685     *
    686     * @see #setLifo
    687     */
    688    public final boolean getLifo() {
    689        return lifo;
    690    }
    691
    692    /**
    693     * Gets whether this pool identifies and logs any abandoned objects.
    694     *
    695     * @return {@code true} if abandoned object removal is configured for this
    696     *         pool and removal events are to be logged otherwise {@code false}
    697     *
    698     * @see AbandonedConfig#getLogAbandoned()
    699     * @since 2.11.0
    700     */
    701    public boolean getLogAbandoned() {
    702        final AbandonedConfig ac = this.abandonedConfig;
    703        return ac != null && ac.getLogAbandoned();
    704    }
    705
    706    /**
    707     * Gets the maximum time a thread has waited to borrow objects from the pool.
    708     *
    709     * @return maximum wait time in milliseconds since the pool was created
    710     * @since 2.12.0
    711     */
    712    public final Duration getMaxBorrowWaitDuration() {
    713        return maxBorrowWaitDuration.get();
    714    }
    715
    716    /**
    717     * Gets the maximum time a thread has waited to borrow objects from the pool.
    718     *
    719     * @return maximum wait time in milliseconds since the pool was created
    720     * @deprecated Use {@link #getMaxBorrowWaitDuration()}.
    721     */
    722    @Deprecated
    723    public final long getMaxBorrowWaitTimeMillis() {
    724        return maxBorrowWaitDuration.get().toMillis();
    725    }
    726
    727    /**
    728     * Gets the maximum number of objects that can be allocated by the pool
    729     * (checked out to clients, or idle awaiting checkout) at a given time. When
    730     * negative, there is no limit to the number of objects that can be
    731     * managed by the pool at one time.
    732     *
    733     * @return the cap on the total number of object instances managed by the
    734     *         pool.
    735     * @see #setMaxTotal
    736     */
    737    public final int getMaxTotal() {
    738        return maxTotal;
    739    }
    740
    741    /**
    742     * Gets the maximum duration the
    743     * {@code borrowObject()} method should block before throwing an
    744     * exception when the pool is exhausted and
    745     * {@link #getBlockWhenExhausted} is true. When less than 0, the
    746     * {@code borrowObject()} method may block indefinitely.
    747     *
    748     * @return the maximum number of milliseconds {@code borrowObject()}
    749     *         will block.
    750     *
    751     * @see #setMaxWait
    752     * @see #setBlockWhenExhausted
    753     * @since 2.11.0
    754     */
    755    public final Duration getMaxWaitDuration() {
    756        return maxWaitDuration;
    757    }
    758
    759    /**
    760     * Gets the maximum amount of time (in milliseconds) the
    761     * {@code borrowObject()} method should block before throwing an
    762     * exception when the pool is exhausted and
    763     * {@link #getBlockWhenExhausted} is true. When less than 0, the
    764     * {@code borrowObject()} method may block indefinitely.
    765     *
    766     * @return the maximum number of milliseconds {@code borrowObject()}
    767     *         will block.
    768     *
    769     * @see #setMaxWait
    770     * @see #setBlockWhenExhausted
    771     * @deprecated Use {@link #getMaxWaitDuration()}.
    772     */
    773    @Deprecated
    774    public final long getMaxWaitMillis() {
    775        return maxWaitDuration.toMillis();
    776    }
    777
    778    /**
    779     * Gets the mean time objects are active for based on the last {@link
    780     * #MEAN_TIMING_STATS_CACHE_SIZE} objects returned to the pool.
    781     * @return mean time an object has been checked out from the pool among
    782     * recently returned objects.
    783     *
    784     * @since 2.12.0
    785     */
    786    public final Duration getMeanActiveDuration() {
    787        return activeTimes.getMeanDuration();
    788    }
    789
    790    /**
    791     * Gets the mean time objects are active for based on the last {@link
    792     * #MEAN_TIMING_STATS_CACHE_SIZE} objects returned to the pool.
    793     * @return mean time an object has been checked out from the pool among
    794     * recently returned objects.
    795     *
    796     * @deprecated Use {@link #getMeanActiveDuration()}.
    797     */
    798    @Deprecated
    799    public final long getMeanActiveTimeMillis() {
    800        return activeTimes.getMean();
    801    }
    802
    803    /**
    804     * Gets the mean time threads wait to borrow an object based on the last {@link
    805     * #MEAN_TIMING_STATS_CACHE_SIZE} objects borrowed from the pool.
    806     *
    807     * @return mean time in milliseconds that a recently served thread has had
    808     * to wait to borrow an object from the pool.
    809     * @since 2.12.0
    810     */
    811    public final Duration getMeanBorrowWaitDuration() {
    812        return waitTimes.getMeanDuration();
    813    }
    814
    815    /**
    816     * Gets the mean time threads wait to borrow an object based on the last {@link
    817     * #MEAN_TIMING_STATS_CACHE_SIZE} objects borrowed from the pool.
    818     *
    819     * @return mean time in milliseconds that a recently served thread has had
    820     * to wait to borrow an object from the pool.
    821     * @deprecated Use {@link #getMeanBorrowWaitDuration()}.
    822     */
    823    @Deprecated
    824    public final long getMeanBorrowWaitTimeMillis() {
    825        return waitTimes.getMean();
    826    }
    827
    828    /**
    829     * Gets the mean time objects are idle for based on the last {@link
    830     * #MEAN_TIMING_STATS_CACHE_SIZE} objects borrowed from the pool.
    831     *
    832     * @return mean time an object has been idle in the pool among recently
    833     * borrowed objects.
    834     * @since 2.12.0
    835     */
    836    public final Duration getMeanIdleDuration() {
    837        return idleTimes.getMeanDuration();
    838    }
    839
    840    /**
    841     * Gets the mean time objects are idle for based on the last {@link
    842     * #MEAN_TIMING_STATS_CACHE_SIZE} objects borrowed from the pool.
    843     *
    844     * @return mean time an object has been idle in the pool among recently
    845     * borrowed objects.
    846     * @deprecated Use {@link #getMeanIdleDuration()}.
    847     */
    848    @Deprecated
    849    public final long getMeanIdleTimeMillis() {
    850        return idleTimes.getMean();
    851    }
    852
    853    /**
    854     * Gets whether to include statistics in exception messages.
    855     * <p>
    856     * 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
    857     * information.
    858     * </p>
    859     *
    860     * @return whether to include statistics in exception messages.
    861     * @since 2.11.0
    862     */
    863    public boolean getMessageStatistics() {
    864        return messageStatistics;
    865    }
    866
    867    /**
    868     * Gets the minimum amount of time an object may sit idle in the pool
    869     * before it is eligible for eviction by the idle object evictor (if any -
    870     * see {@link #setDurationBetweenEvictionRuns(Duration)}). When non-positive,
    871     * no objects will be evicted from the pool due to idle time alone.
    872     *
    873     * @return minimum amount of time an object may sit idle in the pool before
    874     *         it is eligible for eviction
    875     *
    876     * @see #setMinEvictableIdleTimeMillis
    877     * @see #setTimeBetweenEvictionRunsMillis
    878     * @since 2.11.0
    879     */
    880    public final Duration getMinEvictableIdleDuration() {
    881        return minEvictableIdleDuration;
    882    }
    883
    884    /**
    885     * Gets the minimum amount of time an object may sit idle in the pool
    886     * before it is eligible for eviction by the idle object evictor (if any -
    887     * see {@link #setDurationBetweenEvictionRuns(Duration)}). When non-positive,
    888     * no objects will be evicted from the pool due to idle time alone.
    889     *
    890     * @return minimum amount of time an object may sit idle in the pool before
    891     *         it is eligible for eviction
    892     *
    893     * @see #setMinEvictableIdleTimeMillis
    894     * @see #setTimeBetweenEvictionRunsMillis
    895     * @since 2.10.0
    896     * @deprecated Use {@link #getMinEvictableIdleDuration()}.
    897     */
    898    @Deprecated
    899    public final Duration getMinEvictableIdleTime() {
    900        return minEvictableIdleDuration;
    901    }
    902
    903    /**
    904     * Gets the minimum amount of time an object may sit idle in the pool
    905     * before it is eligible for eviction by the idle object evictor (if any -
    906     * see {@link #setTimeBetweenEvictionRunsMillis(long)}). When non-positive,
    907     * no objects will be evicted from the pool due to idle time alone.
    908     *
    909     * @return minimum amount of time an object may sit idle in the pool before
    910     *         it is eligible for eviction
    911     *
    912     * @see #setMinEvictableIdleTimeMillis
    913     * @see #setTimeBetweenEvictionRunsMillis
    914     * @deprecated Use {@link #getMinEvictableIdleDuration()}.
    915     */
    916    @Deprecated
    917    public final long getMinEvictableIdleTimeMillis() {
    918        return minEvictableIdleDuration.toMillis();
    919    }
    920
    921    /**
    922     * Gets the number of instances currently idle in this pool.
    923     * @return count of instances available for checkout from the pool
    924     */
    925    public abstract int getNumIdle();
    926
    927    /**
    928     * Gets the maximum number of objects to examine during each run (if any)
    929     * of the idle object evictor thread. When positive, the number of tests
    930     * performed for a run will be the minimum of the configured value and the
    931     * number of idle instances in the pool. When negative, the number of tests
    932     * performed will be <code>ceil({@link #getNumIdle}/
    933     * abs({@link #getNumTestsPerEvictionRun}))</code> which means that when the
    934     * value is {@code -n} roughly one nth of the idle objects will be
    935     * tested per run.
    936     *
    937     * @return max number of objects to examine during each evictor run
    938     *
    939     * @see #setNumTestsPerEvictionRun
    940     * @see #setTimeBetweenEvictionRunsMillis
    941     */
    942    public final int getNumTestsPerEvictionRun() {
    943        return numTestsPerEvictionRun;
    944    }
    945
    946    /**
    947     * Gets whether a check is made for abandoned objects when an object is borrowed
    948     * from this pool.
    949     *
    950     * @return {@code true} if abandoned object removal is configured to be
    951     *         activated by borrowObject otherwise {@code false}
    952     *
    953     * @see AbandonedConfig#getRemoveAbandonedOnBorrow()
    954     * @since 2.11.0
    955     */
    956    public boolean getRemoveAbandonedOnBorrow() {
    957        final AbandonedConfig ac = this.abandonedConfig;
    958        return ac != null && ac.getRemoveAbandonedOnBorrow();
    959    }
    960
    961    /**
    962     * Gets whether a check is made for abandoned objects when the evictor runs.
    963     *
    964     * @return {@code true} if abandoned object removal is configured to be
    965     *         activated when the evictor runs otherwise {@code false}
    966     *
    967     * @see AbandonedConfig#getRemoveAbandonedOnMaintenance()
    968     * @since 2.11.0
    969     */
    970    public boolean getRemoveAbandonedOnMaintenance() {
    971        final AbandonedConfig ac = this.abandonedConfig;
    972        return ac != null && ac.getRemoveAbandonedOnMaintenance();
    973    }
    974
    975    /**
    976     * Gets the timeout before which an object will be considered to be
    977     * abandoned by this pool.
    978     *
    979     * @return The abandoned object timeout in seconds if abandoned object
    980     *         removal is configured for this pool; Integer.MAX_VALUE otherwise.
    981     *
    982     * @see AbandonedConfig#getRemoveAbandonedTimeoutDuration()
    983     * @see AbandonedConfig#getRemoveAbandonedTimeoutDuration()
    984     * @deprecated Use {@link #getRemoveAbandonedTimeoutDuration()}.
    985     * @since 2.11.0
    986     */
    987    @Deprecated
    988    public int getRemoveAbandonedTimeout() {
    989        return (int) getRemoveAbandonedTimeoutDuration().getSeconds();
    990    }
    991
    992    /**
    993     * Gets the timeout before which an object will be considered to be
    994     * abandoned by this pool.
    995     *
    996     * @return The abandoned object timeout in seconds if abandoned object
    997     *         removal is configured for this pool; Integer.MAX_VALUE otherwise.
    998     *
    999     * @see AbandonedConfig#getRemoveAbandonedTimeoutDuration()
    1000     * @since 2.11.0
    1001     */
    1002    public Duration getRemoveAbandonedTimeoutDuration() {
    1003        final AbandonedConfig ac = this.abandonedConfig;
    1004        return ac != null ? ac.getRemoveAbandonedTimeoutDuration() : DEFAULT_REMOVE_ABANDONED_TIMEOUT;
    1005    }
    1006
    1007    /**
    1008     * Gets the total number of objects returned to this pool over the lifetime of
    1009     * the pool. This excludes attempts to return the same object multiple
    1010     * times.
    1011     * @return the returned object count
    1012     */
    1013    public final long getReturnedCount() {
    1014        return returnedCount.get();
    1015    }
    1016
    1017    /**
    1018     * Gets the minimum amount of time an object may sit idle in the pool
    1019     * before it is eligible for eviction by the idle object evictor (if any -
    1020     * see {@link #setDurationBetweenEvictionRuns(Duration)}),
    1021     * with the extra condition that at least {@code minIdle} object
    1022     * instances remain in the pool. This setting is overridden by
    1023     * {@link #getMinEvictableIdleTime} (that is, if
    1024     * {@link #getMinEvictableIdleTime} is positive, then
    1025     * {@link #getSoftMinEvictableIdleTime} is ignored).
    1026     *
    1027     * @return minimum amount of time an object may sit idle in the pool before
    1028     *         it is eligible for eviction if minIdle instances are available
    1029     *
    1030     * @see #setSoftMinEvictableIdleDuration(Duration)
    1031     * @since 2.11.0
    1032     */
    1033    public final Duration getSoftMinEvictableIdleDuration() {
    1034        return softMinEvictableIdleDuration;
    1035    }
    1036
    1037    /**
    1038     * Gets the minimum amount of time an object may sit idle in the pool
    1039     * before it is eligible for eviction by the idle object evictor (if any -
    1040     * see {@link #setDurationBetweenEvictionRuns(Duration)}),
    1041     * with the extra condition that at least {@code minIdle} object
    1042     * instances remain in the pool. This setting is overridden by
    1043     * {@link #getMinEvictableIdleTime} (that is, if
    1044     * {@link #getMinEvictableIdleTime} is positive, then
    1045     * {@link #getSoftMinEvictableIdleTime} is ignored).
    1046     *
    1047     * @return minimum amount of time an object may sit idle in the pool before
    1048     *         it is eligible for eviction if minIdle instances are available
    1049     *
    1050     * @see #setSoftMinEvictableIdleDuration(Duration)
    1051     * @since 2.10.0
    1052     * @deprecated Use {@link #getSoftMinEvictableIdleDuration}.
    1053     */
    1054    @Deprecated
    1055    public final Duration getSoftMinEvictableIdleTime() {
    1056        return softMinEvictableIdleDuration;
    1057    }
    1058
    1059    /**
    1060     * Gets the minimum amount of time an object may sit idle in the pool
    1061     * before it is eligible for eviction by the idle object evictor (if any -
    1062     * see {@link #setTimeBetweenEvictionRunsMillis(long)}),
    1063     * with the extra condition that at least {@code minIdle} object
    1064     * instances remain in the pool. This setting is overridden by
    1065     * {@link #getMinEvictableIdleTimeMillis} (that is, if
    1066     * {@link #getMinEvictableIdleTimeMillis} is positive, then
    1067     * {@link #getSoftMinEvictableIdleTimeMillis} is ignored).
    1068     *
    1069     * @return minimum amount of time an object may sit idle in the pool before
    1070     *         it is eligible for eviction if minIdle instances are available
    1071     *
    1072     * @see #setSoftMinEvictableIdleTimeMillis
    1073     * @deprecated Use {@link #getSoftMinEvictableIdleTime()}.
    1074     */
    1075    @Deprecated
    1076    public final long getSoftMinEvictableIdleTimeMillis() {
    1077        return softMinEvictableIdleDuration.toMillis();
    1078    }
    1079
    1080    /**
    1081     * Gets the stack trace of an exception as a string.
    1082     * @param e exception to trace
    1083     * @return exception stack trace as a string
    1084     */
    1085    private String getStackTrace(final Exception e) {
    1086        // Need the exception in string form to prevent the retention of
    1087        // references to classes in the stack trace that could trigger a memory
    1088        // leak in a container environment.
    1089        final Writer w = new StringWriter();
    1090        final PrintWriter pw = new PrintWriter(w);
    1091        e.printStackTrace(pw);
    1092        return w.toString();
    1093    }
    1094
    1095    /**
    1096     * Gets a statistics string.
    1097     *
    1098     * @return  a statistics string.
    1099     */
    1100    String getStatsString() {
    1101        // Simply listed in AB order.
    1102        return String.format(
    1103                "activeTimes=%s, blockWhenExhausted=%s, borrowedCount=%,d, closed=%s, createdCount=%,d, destroyedByBorrowValidationCount=%,d, " +
    1104                        "destroyedByEvictorCount=%,d, evictorShutdownTimeoutDuration=%s, fairness=%s, idleTimes=%s, lifo=%s, maxBorrowWaitDuration=%s, " +
    1105                        "maxTotal=%s, maxWaitDuration=%s, minEvictableIdleDuration=%s, numTestsPerEvictionRun=%s, returnedCount=%s, " +
    1106                        "softMinEvictableIdleDuration=%s, testOnBorrow=%s, testOnCreate=%s, testOnReturn=%s, testWhileIdle=%s, " +
    1107                        "durationBetweenEvictionRuns=%s, waitTimes=%s",
    1108                activeTimes.getValues(), blockWhenExhausted, borrowedCount.get(), closed, createdCount.get(), destroyedByBorrowValidationCount.get(),
    1109                destroyedByEvictorCount.get(), evictorShutdownTimeoutDuration, fairness, idleTimes.getValues(), lifo, maxBorrowWaitDuration.get(),
    1110                maxTotal, maxWaitDuration, minEvictableIdleDuration, numTestsPerEvictionRun, returnedCount, softMinEvictableIdleDuration, testOnBorrow,
    1111                testOnCreate, testOnReturn, testWhileIdle, durationBetweenEvictionRuns, waitTimes.getValues());
    1112    }
    1113
    1114    /**
    1115     * Gets the listener used (if any) to receive notifications of exceptions
    1116     * unavoidably swallowed by the pool.
    1117     *
    1118     * @return The listener or {@code null} for no listener
    1119     */
    1120    public final SwallowedExceptionListener getSwallowedExceptionListener() {
    1121        return swallowedExceptionListener;
    1122    }
    1123
    1124    /**
    1125     * Gets whether objects borrowed from the pool will be validated before
    1126     * being returned from the {@code borrowObject()} method. Validation is
    1127     * performed by the {@code validateObject()} method of the factory
    1128     * associated with the pool. If the object fails to validate, it will be
    1129     * removed from the pool and destroyed, and a new attempt will be made to
    1130     * borrow an object from the pool.
    1131     *
    1132     * @return {@code true} if objects are validated before being returned
    1133     *         from the {@code borrowObject()} method
    1134     *
    1135     * @see #setTestOnBorrow
    1136     */
    1137    public final boolean getTestOnBorrow() {
    1138        return testOnBorrow;
    1139    }
    1140
    1141    /**
    1142     * Gets whether objects created for the pool will be validated before
    1143     * being returned from the {@code borrowObject()} method. Validation is
    1144     * performed by the {@code validateObject()} method of the factory
    1145     * associated with the pool. If the object fails to validate, then
    1146     * {@code borrowObject()} will fail.
    1147     *
    1148     * @return {@code true} if newly created objects are validated before
    1149     *         being returned from the {@code borrowObject()} method
    1150     *
    1151     * @see #setTestOnCreate
    1152     *
    1153     * @since 2.2
    1154     */
    1155    public final boolean getTestOnCreate() {
    1156        return testOnCreate;
    1157    }
    1158
    1159    /**
    1160     * Gets whether objects borrowed from the pool will be validated when
    1161     * they are returned to the pool via the {@code returnObject()} method.
    1162     * Validation is performed by the {@code validateObject()} method of
    1163     * the factory associated with the pool. Returning objects that fail validation
    1164     * are destroyed rather then being returned the pool.
    1165     *
    1166     * @return {@code true} if objects are validated on return to
    1167     *         the pool via the {@code returnObject()} method
    1168     *
    1169     * @see #setTestOnReturn
    1170     */
    1171    public final boolean getTestOnReturn() {
    1172        return testOnReturn;
    1173    }
    1174
    1175    /**
    1176     * Gets whether objects sitting idle in the pool will be validated by the
    1177     * idle object evictor (if any - see
    1178     * {@link #setDurationBetweenEvictionRuns(Duration)}). Validation is performed
    1179     * by the {@code validateObject()} method of the factory associated
    1180     * with the pool. If the object fails to validate, it will be removed from
    1181     * the pool and destroyed.
    1182     *
    1183     * @return {@code true} if objects will be validated by the evictor
    1184     *
    1185     * @see #setTestWhileIdle
    1186     * @see #setTimeBetweenEvictionRunsMillis
    1187     */
    1188    public final boolean getTestWhileIdle() {
    1189        return testWhileIdle;
    1190    }
    1191
    1192    /**
    1193     * Gets the duration to sleep between runs of the idle
    1194     * object evictor thread. When non-positive, no idle object evictor thread
    1195     * will be run.
    1196     *
    1197     * @return number of milliseconds to sleep between evictor runs
    1198     *
    1199     * @see #setTimeBetweenEvictionRuns
    1200     * @since 2.10.0
    1201     * @deprecated {@link #getDurationBetweenEvictionRuns()}.
    1202     */
    1203    @Deprecated
    1204    public final Duration getTimeBetweenEvictionRuns() {
    1205        return durationBetweenEvictionRuns;
    1206    }
    1207
    1208    /**
    1209     * Gets the number of milliseconds to sleep between runs of the idle
    1210     * object evictor thread. When non-positive, no idle object evictor thread
    1211     * will be run.
    1212     *
    1213     * @return number of milliseconds to sleep between evictor runs
    1214     *
    1215     * @see #setTimeBetweenEvictionRunsMillis
    1216     * @deprecated Use {@link #getDurationBetweenEvictionRuns()}.
    1217     */
    1218    @Deprecated
    1219    public final long getTimeBetweenEvictionRunsMillis() {
    1220        return durationBetweenEvictionRuns.toMillis();
    1221    }
    1222
    1223    /**
    1224     * Tests whether or not abandoned object removal is configured for this pool.
    1225     *
    1226     * @return true if this pool is configured to detect and remove
    1227     * abandoned objects
    1228     * @since 2.11.0
    1229     */
    1230    public boolean isAbandonedConfig() {
    1231        return abandonedConfig != null;
    1232    }
    1233
    1234    /**
    1235     * Tests whether this pool instance been closed.
    1236     * @return {@code true} when this pool has been closed.
    1237     */
    1238    public final boolean isClosed() {
    1239        return closed;
    1240    }
    1241
    1242    /**
    1243     * Registers the pool with the platform MBean server.
    1244     * The registered name will be
    1245     * {@code jmxNameBase + jmxNamePrefix + i} where i is the least
    1246     * integer greater than or equal to 1 such that the name is not already
    1247     * registered. Swallows MBeanRegistrationException, NotCompliantMBeanException
    1248     * returning null.
    1249     *
    1250     * @param config Pool configuration
    1251     * @param jmxNameBase default base JMX name for this pool
    1252     * @param jmxNamePrefix name prefix
    1253     * @return registered ObjectName, null if registration fails
    1254     */
    1255    private ObjectName jmxRegister(final BaseObjectPoolConfig<T> config,
    1256            final String jmxNameBase, String jmxNamePrefix) {
    1257        ObjectName newObjectName = null;
    1258        final MBeanServer mbs = ManagementFactory.getPlatformMBeanServer();
    1259        int i = 1;
    1260        boolean registered = false;
    1261        String base = config.getJmxNameBase();
    1262        if (base == null) {
    1263            base = jmxNameBase;
    1264        }
    1265        while (!registered) {
    1266            try {
    1267                ObjectName objName;
    1268                // Skip the numeric suffix for the first pool in case there is
    1269                // only one so the names are cleaner.
    1270                if (i == 1) {
    1271                    objName = new ObjectName(base + jmxNamePrefix);
    1272                } else {
    1273                    objName = new ObjectName(base + jmxNamePrefix + i);
    1274                }
    1275                if (!mbs.isRegistered(objName)) {
    1276                    mbs.registerMBean(this, objName);
    1277                    newObjectName = objName;
    1278                    registered = true;
    1279                } else {
    1280                    // Increment the index and try again
    1281                    i++;
    1282                }
    1283            } catch (final MalformedObjectNameException e) {
    1284                if (BaseObjectPoolConfig.DEFAULT_JMX_NAME_PREFIX.equals(
    1285                        jmxNamePrefix) && jmxNameBase.equals(base)) {
    1286                    // Shouldn't happen. Skip registration if it does.
    1287                    registered = true;
    1288                } else {
    1289                    // Must be an invalid name. Use the defaults instead.
    1290                    jmxNamePrefix =
    1291                            BaseObjectPoolConfig.DEFAULT_JMX_NAME_PREFIX;
    1292                    base = jmxNameBase;
    1293                }
    1294            } catch (final InstanceAlreadyExistsException e) {
    1295                // Increment the index and try again
    1296                i++;
    1297            } catch (final MBeanRegistrationException | NotCompliantMBeanException e) {
    1298                // Shouldn't happen. Skip registration if it does.
    1299                registered = true;
    1300            }
    1301        }
    1302        return newObjectName;
    1303    }
    1304
    1305    /**
    1306     * Unregisters this pool's MBean.
    1307     */
    1308    final void jmxUnregister() {
    1309        if (objectName != null) {
    1310            try {
    1311                ManagementFactory.getPlatformMBeanServer().unregisterMBean(objectName);
    1312            } catch (final MBeanRegistrationException | InstanceNotFoundException e) {
    1313                swallowException(e);
    1314            }
    1315        }
    1316    }
    1317
    1318    /**
    1319     * Marks the object as returning to the pool.
    1320     * @param pooledObject instance to return to the keyed pool
    1321     */
    1322    protected void markReturningState(final PooledObject<T> pooledObject) {
    1323        synchronized (pooledObject) {
    1324            if (pooledObject.getState() != PooledObjectState.ALLOCATED) {
    1325                throw new IllegalStateException("Object has already been returned to this pool or is invalid");
    1326            }
    1327            pooledObject.markReturning(); // Keep from being marked abandoned
    1328        }
    1329    }
    1330
    1331    /**
    1332     * Sets the abandoned object removal configuration.
    1333     *
    1334     * @param abandonedConfig the new configuration to use. This is used by value.
    1335     *
    1336     * @see AbandonedConfig
    1337     * @since 2.11.0
    1338     */
    1339    public void setAbandonedConfig(final AbandonedConfig abandonedConfig) {
    1340        this.abandonedConfig = AbandonedConfig.copy(abandonedConfig);
    1341    }
    1342
    1343    /**
    1344     * Sets whether to block when the {@code borrowObject()} method is
    1345     * invoked when the pool is exhausted (the maximum number of "active"
    1346     * objects has been reached).
    1347     *
    1348     * @param blockWhenExhausted    {@code true} if
    1349     *                              {@code borrowObject()} should block
    1350     *                              when the pool is exhausted
    1351     *
    1352     * @see #getBlockWhenExhausted
    1353     */
    1354    public final void setBlockWhenExhausted(final boolean blockWhenExhausted) {
    1355        this.blockWhenExhausted = blockWhenExhausted;
    1356    }
    1357
    1358    /**
    1359     * Sets the receiver with the given configuration.
    1360     *
    1361     * @param config Initialization source.
    1362     */
    1363    protected void setConfig(final BaseObjectPoolConfig<T> config) {
    1364        setLifo(config.getLifo());
    1365        setMaxWait(config.getMaxWaitDuration());
    1366        setBlockWhenExhausted(config.getBlockWhenExhausted());
    1367        setTestOnCreate(config.getTestOnCreate());
    1368        setTestOnBorrow(config.getTestOnBorrow());
    1369        setTestOnReturn(config.getTestOnReturn());
    1370        setTestWhileIdle(config.getTestWhileIdle());
    1371        setNumTestsPerEvictionRun(config.getNumTestsPerEvictionRun());
    1372        setMinEvictableIdleDuration(config.getMinEvictableIdleDuration());
    1373        setDurationBetweenEvictionRuns(config.getDurationBetweenEvictionRuns());
    1374        setSoftMinEvictableIdleDuration(config.getSoftMinEvictableIdleDuration());
    1375        final EvictionPolicy<T> policy = config.getEvictionPolicy();
    1376        if (policy == null) {
    1377            // Use the class name (pre-2.6.0 compatible)
    1378            setEvictionPolicyClassName(config.getEvictionPolicyClassName());
    1379        } else {
    1380            // Otherwise, use the class (2.6.0 feature)
    1381            setEvictionPolicy(policy);
    1382        }
    1383        setEvictorShutdownTimeout(config.getEvictorShutdownTimeoutDuration());
    1384    }
    1385
    1386    /**
    1387     * Sets the number of milliseconds to sleep between runs of the idle object evictor thread.
    1388     * <ul>
    1389     * <li>When positive, the idle object evictor thread starts.</li>
    1390     * <li>When null or non-positive, no idle object evictor thread runs.</li>
    1391     * </ul>
    1392     *
    1393     * @param timeBetweenEvictionRuns
    1394     *            duration to sleep between evictor runs
    1395     *
    1396     * @see #getDurationBetweenEvictionRuns()
    1397     * @since 2.12.0
    1398     */
    1399    public final void setDurationBetweenEvictionRuns(final Duration timeBetweenEvictionRuns) {
    1400        this.durationBetweenEvictionRuns = PoolImplUtils.nonNull(timeBetweenEvictionRuns, BaseObjectPoolConfig.DEFAULT_DURATION_BETWEEN_EVICTION_RUNS);
    1401        startEvictor(this.durationBetweenEvictionRuns);
    1402    }
    1403
    1404    /**
    1405     * Sets the eviction policy for this pool.
    1406     *
    1407     * @param evictionPolicy
    1408     *            the eviction policy for this pool.
    1409     * @since 2.6.0
    1410     */
    1411    public void setEvictionPolicy(final EvictionPolicy<T> evictionPolicy) {
    1412        this.evictionPolicy = evictionPolicy;
    1413    }
    1414
    1415    /**
    1416     * Sets the eviction policy.
    1417     *
    1418     * @param className Eviction policy class name.
    1419     * @param classLoader Load the class from this class loader.
    1420     * @throws LinkageError if the linkage fails
    1421     * @throws ExceptionInInitializerError if the initialization provoked by this method fails
    1422     * @throws ClassNotFoundException if the class cannot be located by the specified class loader
    1423     * @throws IllegalAccessException if this {@code Constructor} object is enforcing Java language access control and the underlying constructor is
    1424     *         inaccessible.
    1425     * @throws IllegalArgumentException if the number of actual and formal parameters differ; if an unwrapping conversion for primitive arguments fails; or if,
    1426     *         after possible unwrapping, a parameter value cannot be converted to the corresponding formal parameter type by a method invocation conversion; if
    1427     *         this constructor pertains to an enum type.
    1428     * @throws InstantiationException if the class that declares the underlying constructor represents an abstract class.
    1429     * @throws InvocationTargetException if the underlying constructor throws an exception.
    1430     * @throws ExceptionInInitializerError if the initialization provoked by this method fails.
    1431     * @throws NoSuchMethodException if a matching method is not found.
    1432     * @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
    1433     *         current class and invocation of {@link SecurityManager#checkPackageAccess s.checkPackageAccess()} denies access to the package of this class.
    1434     */
    1435    @SuppressWarnings("unchecked")
    1436    private void setEvictionPolicy(final String className, final ClassLoader classLoader)
    1437            throws ClassNotFoundException, InstantiationException, IllegalAccessException, InvocationTargetException, NoSuchMethodException {
    1438        final Class<?> clazz = Class.forName(className, true, classLoader);
    1439        final Object policy = clazz.getConstructor().newInstance();
    1440        this.evictionPolicy = (EvictionPolicy<T>) policy;
    1441    }
    1442
    1443    /**
    1444     * Sets the name of the {@link EvictionPolicy} implementation that is used by this pool. The Pool will attempt to
    1445     * load the class using the thread context class loader. If that fails, the use the class loader for the
    1446     * {@link EvictionPolicy} interface.
    1447     *
    1448     * @param evictionPolicyClassName
    1449     *            the fully qualified class name of the new eviction policy
    1450     *
    1451     * @see #getEvictionPolicyClassName()
    1452     * @since 2.6.0 If loading the class using the thread context class loader fails, use the class loader for the
    1453     *        {@link EvictionPolicy} interface.
    1454     */
    1455    public final void setEvictionPolicyClassName(final String evictionPolicyClassName) {
    1456        setEvictionPolicyClassName(evictionPolicyClassName, Thread.currentThread().getContextClassLoader());
    1457    }
    1458
    1459    /**
    1460     * Sets the name of the {@link EvictionPolicy} implementation that is used by this pool. The Pool will attempt to
    1461     * load the class using the given class loader. If that fails, use the class loader for the {@link EvictionPolicy}
    1462     * interface.
    1463     *
    1464     * @param evictionPolicyClassName
    1465     *            the fully qualified class name of the new eviction policy
    1466     * @param classLoader
    1467     *            the class loader to load the given {@code evictionPolicyClassName}.
    1468     *
    1469     * @see #getEvictionPolicyClassName()
    1470     * @since 2.6.0 If loading the class using the given class loader fails, use the class loader for the
    1471     *        {@link EvictionPolicy} interface.
    1472     */
    1473    public final void setEvictionPolicyClassName(final String evictionPolicyClassName, final ClassLoader classLoader) {
    1474        // Getting epClass here and now best matches the caller's environment
    1475        final Class<?> epClass = EvictionPolicy.class;
    1476        final ClassLoader epClassLoader = epClass.getClassLoader();
    1477        try {
    1478            try {
    1479                setEvictionPolicy(evictionPolicyClassName, classLoader);
    1480            } catch (final ClassCastException | ClassNotFoundException e) {
    1481                setEvictionPolicy(evictionPolicyClassName, epClassLoader);
    1482            }
    1483        } catch (final ClassCastException e) {
    1484            throw new IllegalArgumentException("Class " + evictionPolicyClassName + " from class loaders [" +
    1485                    classLoader + ", " + epClassLoader + "] do not implement " + EVICTION_POLICY_TYPE_NAME);
    1486        } catch (final ClassNotFoundException | InstantiationException | IllegalAccessException |
    1487                InvocationTargetException | NoSuchMethodException e) {
    1488            throw new IllegalArgumentException(
    1489                    "Unable to create " + EVICTION_POLICY_TYPE_NAME + " instance of type " + evictionPolicyClassName,
    1490                    e);
    1491        }
    1492    }
    1493
    1494    /**
    1495     * Sets the timeout that will be used when waiting for the Evictor to shutdown if this pool is closed and it is the
    1496     * only pool still using the value for the Evictor.
    1497     *
    1498     * @param evictorShutdownTimeout the timeout in milliseconds that will be used while waiting for the Evictor
    1499     *                                     to shut down.
    1500     * @since 2.10.0
    1501     */
    1502    public final void setEvictorShutdownTimeout(final Duration evictorShutdownTimeout) {
    1503        this.evictorShutdownTimeoutDuration = PoolImplUtils.nonNull(evictorShutdownTimeout, BaseObjectPoolConfig.DEFAULT_EVICTOR_SHUTDOWN_TIMEOUT);
    1504    }
    1505
    1506    /**
    1507     * Sets the timeout that will be used when waiting for the Evictor to shutdown if this pool is closed and it is the
    1508     * only pool still using the value for the Evictor.
    1509     *
    1510     * @param evictorShutdownTimeoutMillis the timeout in milliseconds that will be used while waiting for the Evictor
    1511     *                                     to shut down.
    1512     * @deprecated Use {@link #setEvictorShutdownTimeout(Duration)}.
    1513     */
    1514    @Deprecated
    1515    public final void setEvictorShutdownTimeoutMillis(final long evictorShutdownTimeoutMillis) {
    1516        setEvictorShutdownTimeout(Duration.ofMillis(evictorShutdownTimeoutMillis));
    1517    }
    1518
    1519    /**
    1520     * Sets whether the pool has LIFO (last in, first out) behavior with
    1521     * respect to idle objects - always returning the most recently used object
    1522     * from the pool, or as a FIFO (first in, first out) queue, where the pool
    1523     * always returns the oldest object in the idle object pool.
    1524     *
    1525     * @param lifo  {@code true} if the pool is to be configured with LIFO
    1526     *              behavior or {@code false} if the pool is to be
    1527     *              configured with FIFO behavior
    1528     *
    1529     * @see #getLifo()
    1530     */
    1531    public final void setLifo(final boolean lifo) {
    1532        this.lifo = lifo;
    1533    }
    1534
    1535    /**
    1536     * Sets the cap on the number of objects that can be allocated by the pool
    1537     * (checked out to clients, or idle awaiting checkout) at a given time. Use
    1538     * a negative value for no limit.
    1539     *
    1540     * @param maxTotal  The cap on the total number of object instances managed
    1541     *                  by the pool. Negative values mean that there is no limit
    1542     *                  to the number of objects allocated by the pool.
    1543     *
    1544     * @see #getMaxTotal
    1545     */
    1546    public final void setMaxTotal(final int maxTotal) {
    1547        this.maxTotal = maxTotal;
    1548    }
    1549
    1550    /**
    1551     * Sets the maximum duration the
    1552     * {@code borrowObject()} method should block before throwing an
    1553     * exception when the pool is exhausted and
    1554     * {@link #getBlockWhenExhausted} is true. When less than 0, the
    1555     * {@code borrowObject()} method may block indefinitely.
    1556     *
    1557     * @param maxWaitDuration the maximum duration
    1558     *                      {@code borrowObject()} will block or negative
    1559     *                      for indefinitely.
    1560     *
    1561     * @see #getMaxWaitDuration
    1562     * @see #setBlockWhenExhausted
    1563     * @since 2.11.0
    1564     */
    1565    public final void setMaxWait(final Duration maxWaitDuration) {
    1566        this.maxWaitDuration = PoolImplUtils.nonNull(maxWaitDuration, BaseObjectPoolConfig.DEFAULT_MAX_WAIT);
    1567    }
    1568
    1569    /**
    1570     * Sets the maximum amount of time (in milliseconds) the
    1571     * {@code borrowObject()} method should block before throwing an
    1572     * exception when the pool is exhausted and
    1573     * {@link #getBlockWhenExhausted} is true. When less than 0, the
    1574     * {@code borrowObject()} method may block indefinitely.
    1575     *
    1576     * @param maxWaitMillis the maximum number of milliseconds
    1577     *                      {@code borrowObject()} will block or negative
    1578     *                      for indefinitely.
    1579     *
    1580     * @see #getMaxWaitDuration
    1581     * @see #setBlockWhenExhausted
    1582     * @deprecated Use {@link #setMaxWait}.
    1583     */
    1584    @Deprecated
    1585    public final void setMaxWaitMillis(final long maxWaitMillis) {
    1586        setMaxWait(Duration.ofMillis(maxWaitMillis));
    1587    }
    1588
    1589    /**
    1590     * Sets whether to include statistics in exception messages.
    1591     * <p>
    1592     * 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
    1593     * information.
    1594     * </p>
    1595     *
    1596     * @param messagesDetails whether to include statistics in exception messages.
    1597     * @since 2.11.0
    1598     */
    1599    public void setMessagesStatistics(final boolean messagesDetails) {
    1600        this.messageStatistics = messagesDetails;
    1601    }
    1602
    1603    /**
    1604     * Sets the minimum amount of time an object may sit idle in the pool
    1605     * before it is eligible for eviction by the idle object evictor (if any -
    1606     * see {@link #setDurationBetweenEvictionRuns(Duration)}). When non-positive,
    1607     * no objects will be evicted from the pool due to idle time alone.
    1608     *
    1609     * @param minEvictableIdleTime
    1610     *            minimum amount of time an object may sit idle in the pool
    1611     *            before it is eligible for eviction
    1612     *
    1613     * @see #getMinEvictableIdleTime
    1614     * @see #setTimeBetweenEvictionRuns
    1615     * @since 2.11.0
    1616     * @deprecated Use {@link #setMinEvictableIdleDuration(Duration)}.
    1617     */
    1618    @Deprecated
    1619    public final void setMinEvictableIdle(final Duration minEvictableIdleTime) {
    1620        this.minEvictableIdleDuration = PoolImplUtils.nonNull(minEvictableIdleTime, BaseObjectPoolConfig.DEFAULT_MIN_EVICTABLE_IDLE_DURATION);
    1621    }
    1622
    1623    /**
    1624     * Sets the minimum amount of time an object may sit idle in the pool
    1625     * before it is eligible for eviction by the idle object evictor (if any -
    1626     * see {@link #setDurationBetweenEvictionRuns(Duration)}). When non-positive,
    1627     * no objects will be evicted from the pool due to idle time alone.
    1628     *
    1629     * @param minEvictableIdleTime
    1630     *            minimum amount of time an object may sit idle in the pool
    1631     *            before it is eligible for eviction
    1632     *
    1633     * @see #getMinEvictableIdleTime
    1634     * @see #setTimeBetweenEvictionRuns
    1635     * @since 2.12.0
    1636     */
    1637    public final void setMinEvictableIdleDuration(final Duration minEvictableIdleTime) {
    1638        this.minEvictableIdleDuration = PoolImplUtils.nonNull(minEvictableIdleTime, BaseObjectPoolConfig.DEFAULT_MIN_EVICTABLE_IDLE_DURATION);
    1639    }
    1640
    1641    /**
    1642     * Sets the minimum amount of time an object may sit idle in the pool
    1643     * before it is eligible for eviction by the idle object evictor (if any -
    1644     * see {@link #setDurationBetweenEvictionRuns(Duration)}). When non-positive,
    1645     * no objects will be evicted from the pool due to idle time alone.
    1646     *
    1647     * @param minEvictableIdleTime
    1648     *            minimum amount of time an object may sit idle in the pool
    1649     *            before it is eligible for eviction
    1650     *
    1651     * @see #getMinEvictableIdleTime
    1652     * @see #setTimeBetweenEvictionRuns
    1653     * @since 2.10.0
    1654     * @deprecated Use {@link #setMinEvictableIdleDuration(Duration)}.
    1655     */
    1656    @Deprecated
    1657    public final void setMinEvictableIdleTime(final Duration minEvictableIdleTime) {
    1658        this.minEvictableIdleDuration = PoolImplUtils.nonNull(minEvictableIdleTime, BaseObjectPoolConfig.DEFAULT_MIN_EVICTABLE_IDLE_DURATION);
    1659    }
    1660
    1661    /**
    1662     * Sets the minimum amount of time an object may sit idle in the pool
    1663     * before it is eligible for eviction by the idle object evictor (if any -
    1664     * see {@link #setTimeBetweenEvictionRunsMillis(long)}). When non-positive,
    1665     * no objects will be evicted from the pool due to idle time alone.
    1666     *
    1667     * @param minEvictableIdleTimeMillis
    1668     *            minimum amount of time an object may sit idle in the pool
    1669     *            before it is eligible for eviction
    1670     *
    1671     * @see #getMinEvictableIdleTimeMillis
    1672     * @see #setTimeBetweenEvictionRunsMillis
    1673     * @deprecated Use {@link #setMinEvictableIdleTime(Duration)}.
    1674     */
    1675    @Deprecated
    1676    public final void setMinEvictableIdleTimeMillis(final long minEvictableIdleTimeMillis) {
    1677        setMinEvictableIdleTime(Duration.ofMillis(minEvictableIdleTimeMillis));
    1678    }
    1679
    1680    /**
    1681     * Sets the maximum number of objects to examine during each run (if any)
    1682     * of the idle object evictor thread. When positive, the number of tests
    1683     * performed for a run will be the minimum of the configured value and the
    1684     * number of idle instances in the pool. When negative, the number of tests
    1685     * performed will be <code>ceil({@link #getNumIdle}/
    1686     * abs({@link #getNumTestsPerEvictionRun}))</code> which means that when the
    1687     * value is {@code -n} roughly one nth of the idle objects will be
    1688     * tested per run.
    1689     *
    1690     * @param numTestsPerEvictionRun
    1691     *            max number of objects to examine during each evictor run
    1692     *
    1693     * @see #getNumTestsPerEvictionRun
    1694     * @see #setTimeBetweenEvictionRunsMillis
    1695     */
    1696    public final void setNumTestsPerEvictionRun(final int numTestsPerEvictionRun) {
    1697        this.numTestsPerEvictionRun = numTestsPerEvictionRun;
    1698    }
    1699
    1700    /**
    1701     * Sets the minimum amount of time an object may sit idle in the pool
    1702     * before it is eligible for eviction by the idle object evictor (if any -
    1703     * see {@link #setDurationBetweenEvictionRuns(Duration)}),
    1704     * with the extra condition that at least {@code minIdle} object
    1705     * instances remain in the pool. This setting is overridden by
    1706     * {@link #getMinEvictableIdleTime} (that is, if
    1707     * {@link #getMinEvictableIdleTime} is positive, then
    1708     * {@link #getSoftMinEvictableIdleTime} is ignored).
    1709     *
    1710     * @param softMinEvictableIdleTime
    1711     *            minimum amount of time an object may sit idle in the pool
    1712     *            before it is eligible for eviction if minIdle instances are
    1713     *            available
    1714     *
    1715     * @see #getSoftMinEvictableIdleTimeMillis
    1716     * @since 2.11.0
    1717     * @deprecated Use {@link #setSoftMinEvictableIdleDuration(Duration)}.
    1718     */
    1719    @Deprecated
    1720    public final void setSoftMinEvictableIdle(final Duration softMinEvictableIdleTime) {
    1721        this.softMinEvictableIdleDuration = PoolImplUtils.nonNull(softMinEvictableIdleTime, BaseObjectPoolConfig.DEFAULT_SOFT_MIN_EVICTABLE_IDLE_DURATION);
    1722    }
    1723
    1724    /**
    1725     * Sets the minimum amount of time an object may sit idle in the pool
    1726     * before it is eligible for eviction by the idle object evictor (if any -
    1727     * see {@link #setDurationBetweenEvictionRuns(Duration)}),
    1728     * with the extra condition that at least {@code minIdle} object
    1729     * instances remain in the pool. This setting is overridden by
    1730     * {@link #getMinEvictableIdleTime} (that is, if
    1731     * {@link #getMinEvictableIdleTime} is positive, then
    1732     * {@link #getSoftMinEvictableIdleTime} is ignored).
    1733     *
    1734     * @param softMinEvictableIdleTime
    1735     *            minimum amount of time an object may sit idle in the pool
    1736     *            before it is eligible for eviction if minIdle instances are
    1737     *            available
    1738     *
    1739     * @see #getSoftMinEvictableIdleTimeMillis
    1740     * @since 2.12.0
    1741     */
    1742    public final void setSoftMinEvictableIdleDuration(final Duration softMinEvictableIdleTime) {
    1743        this.softMinEvictableIdleDuration = PoolImplUtils.nonNull(softMinEvictableIdleTime, BaseObjectPoolConfig.DEFAULT_SOFT_MIN_EVICTABLE_IDLE_DURATION);
    1744    }
    1745
    1746    /**
    1747     * Sets the minimum amount of time an object may sit idle in the pool
    1748     * before it is eligible for eviction by the idle object evictor (if any -
    1749     * see {@link #setDurationBetweenEvictionRuns(Duration)}),
    1750     * with the extra condition that at least {@code minIdle} object
    1751     * instances remain in the pool. This setting is overridden by
    1752     * {@link #getMinEvictableIdleTime} (that is, if
    1753     * {@link #getMinEvictableIdleTime} is positive, then
    1754     * {@link #getSoftMinEvictableIdleTime} is ignored).
    1755     *
    1756     * @param softMinEvictableIdleTime
    1757     *            minimum amount of time an object may sit idle in the pool
    1758     *            before it is eligible for eviction if minIdle instances are
    1759     *            available
    1760     *
    1761     * @see #getSoftMinEvictableIdleTimeMillis
    1762     * @since 2.10.0
    1763     * @deprecated Use {@link #setSoftMinEvictableIdleDuration(Duration)}.
    1764     */
    1765    @Deprecated
    1766    public final void setSoftMinEvictableIdleTime(final Duration softMinEvictableIdleTime) {
    1767        this.softMinEvictableIdleDuration = PoolImplUtils.nonNull(softMinEvictableIdleTime, BaseObjectPoolConfig.DEFAULT_SOFT_MIN_EVICTABLE_IDLE_DURATION);
    1768    }
    1769
    1770    /**
    1771     * Sets the minimum amount of time an object may sit idle in the pool
    1772     * before it is eligible for eviction by the idle object evictor (if any -
    1773     * see {@link #setTimeBetweenEvictionRunsMillis(long)}),
    1774     * with the extra condition that at least {@code minIdle} object
    1775     * instances remain in the pool. This setting is overridden by
    1776     * {@link #getMinEvictableIdleTimeMillis} (that is, if
    1777     * {@link #getMinEvictableIdleTimeMillis} is positive, then
    1778     * {@link #getSoftMinEvictableIdleTimeMillis} is ignored).
    1779     *
    1780     * @param softMinEvictableIdleTimeMillis
    1781     *            minimum amount of time an object may sit idle in the pool
    1782     *            before it is eligible for eviction if minIdle instances are
    1783     *            available
    1784     *
    1785     * @see #getSoftMinEvictableIdleTimeMillis
    1786     * @deprecated Use {@link #setSoftMinEvictableIdleDuration(Duration)}.
    1787     */
    1788    @Deprecated
    1789    public final void setSoftMinEvictableIdleTimeMillis(final long softMinEvictableIdleTimeMillis) {
    1790        setSoftMinEvictableIdleTime(Duration.ofMillis(softMinEvictableIdleTimeMillis));
    1791    }
    1792
    1793    /**
    1794     * Sets the listener used (if any) to receive notifications of exceptions
    1795     * unavoidably swallowed by the pool.
    1796     *
    1797     * @param swallowedExceptionListener    The listener or {@code null}
    1798     *                                      for no listener
    1799     */
    1800    public final void setSwallowedExceptionListener(
    1801            final SwallowedExceptionListener swallowedExceptionListener) {
    1802        this.swallowedExceptionListener = swallowedExceptionListener;
    1803    }
    1804
    1805    /**
    1806     * Sets whether objects borrowed from the pool will be validated before
    1807     * being returned from the {@code borrowObject()} method. Validation is
    1808     * performed by the {@code validateObject()} method of the factory
    1809     * associated with the pool. If the object fails to validate, it will be
    1810     * removed from the pool and destroyed, and a new attempt will be made to
    1811     * borrow an object from the pool.
    1812     *
    1813     * @param testOnBorrow  {@code true} if objects should be validated
    1814     *                      before being returned from the
    1815     *                      {@code borrowObject()} method
    1816     *
    1817     * @see #getTestOnBorrow
    1818     */
    1819    public final void setTestOnBorrow(final boolean testOnBorrow) {
    1820        this.testOnBorrow = testOnBorrow;
    1821    }
    1822
    1823    /**
    1824     * Sets whether objects created for the pool will be validated before
    1825     * being returned from the {@code borrowObject()} method. Validation is
    1826     * performed by the {@code validateObject()} method of the factory
    1827     * associated with the pool. If the object fails to validate, then
    1828     * {@code borrowObject()} will fail.
    1829     *
    1830     * @param testOnCreate  {@code true} if newly created objects should be
    1831     *                      validated before being returned from the
    1832     *                      {@code borrowObject()} method
    1833     *
    1834     * @see #getTestOnCreate
    1835     *
    1836     * @since 2.2
    1837     */
    1838    public final void setTestOnCreate(final boolean testOnCreate) {
    1839        this.testOnCreate = testOnCreate;
    1840    }
    1841
    1842    /**
    1843     * Sets whether objects borrowed from the pool will be validated when
    1844     * they are returned to the pool via the {@code returnObject()} method.
    1845     * Validation is performed by the {@code validateObject()} method of
    1846     * the factory associated with the pool. Returning objects that fail validation
    1847     * are destroyed rather then being returned the pool.
    1848     *
    1849     * @param testOnReturn {@code true} if objects are validated on
    1850     *                     return to the pool via the
    1851     *                     {@code returnObject()} method
    1852     *
    1853     * @see #getTestOnReturn
    1854     */
    1855    public final void setTestOnReturn(final boolean testOnReturn) {
    1856        this.testOnReturn = testOnReturn;
    1857    }
    1858
    1859    /**
    1860     * Sets whether objects sitting idle in the pool will be validated by the
    1861     * idle object evictor (if any - see
    1862     * {@link #setDurationBetweenEvictionRuns(Duration)}). Validation is performed
    1863     * by the {@code validateObject()} method of the factory associated
    1864     * with the pool. If the object fails to validate, it will be removed from
    1865     * the pool and destroyed.  Note that setting this property has no effect
    1866     * unless the idle object evictor is enabled by setting
    1867     * {@code timeBetweenEvictionRunsMillis} to a positive value.
    1868     *
    1869     * @param testWhileIdle
    1870     *            {@code true} so objects will be validated by the evictor
    1871     *
    1872     * @see #getTestWhileIdle
    1873     * @see #setTimeBetweenEvictionRuns
    1874     */
    1875    public final void setTestWhileIdle(final boolean testWhileIdle) {
    1876        this.testWhileIdle = testWhileIdle;
    1877    }
    1878
    1879    /**
    1880     * Sets the number of milliseconds to sleep between runs of the idle object evictor thread.
    1881     * <ul>
    1882     * <li>When positive, the idle object evictor thread starts.</li>
    1883     * <li>When non-positive, no idle object evictor thread runs.</li>
    1884     * </ul>
    1885     *
    1886     * @param timeBetweenEvictionRuns
    1887     *            duration to sleep between evictor runs
    1888     *
    1889     * @see #getDurationBetweenEvictionRuns()
    1890     * @since 2.10.0
    1891     * @deprecated Use {@link #setDurationBetweenEvictionRuns(Duration)}.
    1892     */
    1893    @Deprecated
    1894    public final void setTimeBetweenEvictionRuns(final Duration timeBetweenEvictionRuns) {
    1895        this.durationBetweenEvictionRuns = PoolImplUtils.nonNull(timeBetweenEvictionRuns, BaseObjectPoolConfig.DEFAULT_DURATION_BETWEEN_EVICTION_RUNS);
    1896        startEvictor(this.durationBetweenEvictionRuns);
    1897    }
    1898
    1899    /**
    1900     * Sets the number of milliseconds to sleep between runs of the idle object evictor thread.
    1901     * <ul>
    1902     * <li>When positive, the idle object evictor thread starts.</li>
    1903     * <li>When non-positive, no idle object evictor thread runs.</li>
    1904     * </ul>
    1905     *
    1906     * @param timeBetweenEvictionRunsMillis
    1907     *            number of milliseconds to sleep between evictor runs
    1908     *
    1909     * @see #getDurationBetweenEvictionRuns()
    1910     * @deprecated Use {@link #setDurationBetweenEvictionRuns(Duration)}.
    1911     */
    1912    @Deprecated
    1913    public final void setTimeBetweenEvictionRunsMillis(final long timeBetweenEvictionRunsMillis) {
    1914        setTimeBetweenEvictionRuns(Duration.ofMillis(timeBetweenEvictionRunsMillis));
    1915    }
    1916
    1917    /**
    1918     * <p>Starts the evictor with the given delay. If there is an evictor
    1919     * running when this method is called, it is stopped and replaced with a
    1920     * new evictor with the specified delay.</p>
    1921     *
    1922     * <p>This method needs to be final, since it is called from a constructor.
    1923     * See POOL-195.</p>
    1924     *
    1925     * @param delay time in milliseconds before start and between eviction runs
    1926     */
    1927    final void startEvictor(final Duration delay) {
    1928        synchronized (evictionLock) {
    1929            final boolean isPositiverDelay = PoolImplUtils.isPositive(delay);
    1930            if (evictor == null) { // Starting evictor for the first time or after a cancel
    1931                if (isPositiverDelay) { // Starting new evictor
    1932                    evictor = new Evictor();
    1933                    EvictionTimer.schedule(evictor, delay, delay);
    1934                }
    1935            } else if (isPositiverDelay) { // Stop or restart of existing evictor: Restart
    1936                synchronized (EvictionTimer.class) { // Ensure no cancel can happen between cancel / schedule calls
    1937                    EvictionTimer.cancel(evictor, evictorShutdownTimeoutDuration, true);
    1938                    evictor = null;
    1939                    evictionIterator = null;
    1940                    evictor = new Evictor();
    1941                    EvictionTimer.schedule(evictor, delay, delay);
    1942                }
    1943            } else { // Stopping evictor
    1944                EvictionTimer.cancel(evictor, evictorShutdownTimeoutDuration, false);
    1945            }
    1946        }
    1947    }
    1948
    1949    /**
    1950     * Stops the evictor.
    1951     */
    1952    void stopEvictor() {
    1953        startEvictor(Duration.ofMillis(-1L));
    1954    }
    1955
    1956    /**
    1957     * Swallows an exception and notifies the configured listener for swallowed
    1958     * exceptions queue.
    1959     *
    1960     * @param swallowException exception to be swallowed
    1961     */
    1962    final void swallowException(final Exception swallowException) {
    1963        final SwallowedExceptionListener listener = getSwallowedExceptionListener();
    1964
    1965        if (listener == null) {
    1966            return;
    1967        }
    1968
    1969        try {
    1970            listener.onSwallowException(swallowException);
    1971        } catch (final VirtualMachineError e) {
    1972            throw e;
    1973        } catch (final Throwable ignored) {
    1974            // Ignore. Enjoy the irony.
    1975        }
    1976    }
    1977
    1978    @Override
    1979    protected void toStringAppendFields(final StringBuilder builder) {
    1980        builder.append("maxTotal=");
    1981        builder.append(maxTotal);
    1982        builder.append(", blockWhenExhausted=");
    1983        builder.append(blockWhenExhausted);
    1984        builder.append(", maxWaitDuration=");
    1985        builder.append(maxWaitDuration);
    1986        builder.append(", lifo=");
    1987        builder.append(lifo);
    1988        builder.append(", fairness=");
    1989        builder.append(fairness);
    1990        builder.append(", testOnCreate=");
    1991        builder.append(testOnCreate);
    1992        builder.append(", testOnBorrow=");
    1993        builder.append(testOnBorrow);
    1994        builder.append(", testOnReturn=");
    1995        builder.append(testOnReturn);
    1996        builder.append(", testWhileIdle=");
    1997        builder.append(testWhileIdle);
    1998        builder.append(", durationBetweenEvictionRuns=");
    1999        builder.append(durationBetweenEvictionRuns);
    2000        builder.append(", numTestsPerEvictionRun=");
    2001        builder.append(numTestsPerEvictionRun);
    2002        builder.append(", minEvictableIdleTimeDuration=");
    2003        builder.append(minEvictableIdleDuration);
    2004        builder.append(", softMinEvictableIdleTimeDuration=");
    2005        builder.append(softMinEvictableIdleDuration);
    2006        builder.append(", evictionPolicy=");
    2007        builder.append(evictionPolicy);
    2008        builder.append(", closeLock=");
    2009        builder.append(closeLock);
    2010        builder.append(", closed=");
    2011        builder.append(closed);
    2012        builder.append(", evictionLock=");
    2013        builder.append(evictionLock);
    2014        builder.append(", evictor=");
    2015        builder.append(evictor);
    2016        builder.append(", evictionIterator=");
    2017        builder.append(evictionIterator);
    2018        builder.append(", factoryClassLoader=");
    2019        builder.append(factoryClassLoader);
    2020        builder.append(", oname=");
    2021        builder.append(objectName);
    2022        builder.append(", creationStackTrace=");
    2023        builder.append(creationStackTrace);
    2024        builder.append(", borrowedCount=");
    2025        builder.append(borrowedCount);
    2026        builder.append(", returnedCount=");
    2027        builder.append(returnedCount);
    2028        builder.append(", createdCount=");
    2029        builder.append(createdCount);
    2030        builder.append(", destroyedCount=");
    2031        builder.append(destroyedCount);
    2032        builder.append(", destroyedByEvictorCount=");
    2033        builder.append(destroyedByEvictorCount);
    2034        builder.append(", destroyedByBorrowValidationCount=");
    2035        builder.append(destroyedByBorrowValidationCount);
    2036        builder.append(", activeTimes=");
    2037        builder.append(activeTimes);
    2038        builder.append(", idleTimes=");
    2039        builder.append(idleTimes);
    2040        builder.append(", waitTimes=");
    2041        builder.append(waitTimes);
    2042        builder.append(", maxBorrowWaitDuration=");
    2043        builder.append(maxBorrowWaitDuration);
    2044        builder.append(", swallowedExceptionListener=");
    2045        builder.append(swallowedExceptionListener);
    2046    }
    2047
    2048    /**
    2049     * Updates statistics after an object is borrowed from the pool.
    2050     *
    2051     * @param p object borrowed from the pool
    2052     * @param waitDuration that the borrowing thread had to wait
    2053     */
    2054    final void updateStatsBorrow(final PooledObject<T> p, final Duration waitDuration) {
    2055        borrowedCount.incrementAndGet();
    2056        idleTimes.add(p.getIdleDuration());
    2057        waitTimes.add(waitDuration);
    2058
    2059        // lock-free optimistic-locking maximum
    2060        Duration currentMaxDuration;
    2061        do {
    2062            currentMaxDuration = maxBorrowWaitDuration.get();
    2063            if (currentMaxDuration.compareTo(waitDuration) >= 0) {
    2064                break;
    2065            }
    2066        } while (!maxBorrowWaitDuration.compareAndSet(currentMaxDuration, waitDuration));
    2067    }
    2068
    2069    /**
    2070     * Updates statistics after an object is returned to the pool.
    2071     *
    2072     * @param activeTime the amount of time (in milliseconds) that the returning
    2073     * object was checked out
    2074     */
    2075    final void updateStatsReturn(final Duration activeTime) {
    2076        returnedCount.incrementAndGet();
    2077        activeTimes.add(activeTime);
    2078    }
    2079
    2080
    2081}