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