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