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