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