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