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