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