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