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      final 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     final class Evictor implements Runnable {
121 
122         private ScheduledFuture<?> scheduledFuture;
123 
124         /**
125          * Cancels the scheduled future.
126          */
127         void cancel() {
128             scheduledFuture.cancel(false);
129         }
130 
131         BaseGenericObjectPool<T> owner() {
132             return BaseGenericObjectPool.this;
133         }
134 
135         /**
136          * Run pool maintenance.  Evict objects qualifying for eviction and then
137          * ensure that the minimum number of idle instances are available.
138          * Since the Timer that invokes Evictors is shared for all Pools but
139          * pools may exist in different class loaders, the Evictor ensures that
140          * any actions taken are under the class loader of the factory
141          * associated with the pool.
142          */
143         @Override
144         public void run() {
145             final ClassLoader savedClassLoader = Thread.currentThread().getContextClassLoader();
146             try {
147                 if (factoryClassLoader != null) {
148                     // Set the class loader for the factory
149                     final ClassLoader cl = factoryClassLoader.get();
150                     if (cl == null) {
151                         // The pool has been dereferenced and the class loader
152                         // GC'd. Cancel this timer so the pool can be GC'd as
153                         // well.
154                         cancel();
155                         return;
156                     }
157                     Thread.currentThread().setContextClassLoader(cl);
158                 }
159 
160                 // Evict from the pool
161                 try {
162                     evict();
163                 } catch (final Exception e) {
164                     swallowException(e);
165                 } catch (final OutOfMemoryError oome) {
166                     // Log problem but give evictor thread a chance to continue
167                     // in case error is recoverable
168                     oome.printStackTrace(System.err);
169                 }
170                 // Re-create idle instances.
171                 try {
172                     ensureMinIdle();
173                 } catch (final Exception e) {
174                     swallowException(e);
175                 }
176             } finally {
177                 // Restore the previous CCL
178                 Thread.currentThread().setContextClassLoader(savedClassLoader);
179             }
180         }
181 
182         /**
183          * Sets the scheduled future.
184          *
185          * @param scheduledFuture the scheduled future.
186          */
187         void setScheduledFuture(final ScheduledFuture<?> scheduledFuture) {
188             this.scheduledFuture = scheduledFuture;
189         }
190 
191         @Override
192         public String toString() {
193             return getClass().getName() + " [scheduledFuture=" + scheduledFuture + "]";
194         }
195 
196     }
197 
198     /**
199      * Wrapper for objects under management by the pool.
200      *
201      * GenericObjectPool and GenericKeyedObjectPool maintain references to all
202      * objects under management using maps keyed on the objects. This wrapper
203      * class ensures that objects can work as hash keys.
204      *
205      * @param <T> type of objects in the pool
206      */
207     static class IdentityWrapper<T> {
208         /** 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 final 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      * @see #setTimeBetweenEvictionRuns
583      * @since 2.11.0
584      */
585     public final Duration getDurationBetweenEvictionRuns() {
586         return durationBetweenEvictionRuns;
587     }
588 
589     /**
590      * Gets the {@link EvictionPolicy} defined for this pool.
591      *
592      * @return the eviction policy
593      * @since 2.4
594      * @since 2.6.0 Changed access from protected to public.
595      */
596     public EvictionPolicy<T> getEvictionPolicy() {
597         return evictionPolicy;
598     }
599 
600     /**
601      * Gets the name of the {@link EvictionPolicy} implementation that is
602      * used by this pool.
603      *
604      * @return  The fully qualified class name of the {@link EvictionPolicy}
605      * @see #setEvictionPolicyClassName(String)
606      */
607     public final String getEvictionPolicyClassName() {
608         return evictionPolicy.getClass().getName();
609     }
610 
611     /**
612      * Gets the timeout that will be used when waiting for the Evictor to
613      * shutdown if this pool is closed and it is the only pool still using the
614      * the value for the Evictor.
615      *
616      * @return  The timeout that will be used while waiting for
617      *          the Evictor to shut down.
618      * @since 2.10.0
619      * @deprecated Use {@link #getEvictorShutdownTimeoutDuration()}.
620      */
621     @Deprecated
622     public final Duration getEvictorShutdownTimeout() {
623         return evictorShutdownTimeoutDuration;
624     }
625 
626     /**
627      * Gets the timeout that will be used when waiting for the Evictor to
628      * shutdown if this pool is closed and it is the only pool still using the
629      * the value for the Evictor.
630      *
631      * @return  The timeout that will be used while waiting for
632      *          the Evictor to shut down.
633      * @since 2.11.0
634      */
635     public final Duration getEvictorShutdownTimeoutDuration() {
636         return evictorShutdownTimeoutDuration;
637     }
638 
639     /**
640      * Gets the timeout that will be used when waiting for the Evictor to
641      * shutdown if this pool is closed and it is the only pool still using the
642      * the value for the Evictor.
643      *
644      * @return  The timeout in milliseconds that will be used while waiting for
645      *          the Evictor to shut down.
646      * @deprecated Use {@link #getEvictorShutdownTimeoutDuration()}.
647      */
648     @Deprecated
649     public final long getEvictorShutdownTimeoutMillis() {
650         return evictorShutdownTimeoutDuration.toMillis();
651     }
652 
653     /**
654      * Gets whether or not the pool serves threads waiting to borrow objects fairly.
655      * True means that waiting threads are served as if waiting in a FIFO queue.
656      *
657      * @return {@code true} if waiting threads are to be served
658      *             by the pool in arrival order
659      */
660     public final boolean getFairness() {
661         return fairness;
662     }
663 
664     /**
665      * Gets the name under which the pool has been registered with the
666      * platform MBean server or {@code null} if the pool has not been
667      * registered.
668      * @return the JMX name
669      */
670     public final ObjectName getJmxName() {
671         return objectName;
672     }
673 
674     /**
675      * Gets whether the pool has LIFO (last in, first out) behavior with
676      * respect to idle objects - always returning the most recently used object
677      * from the pool, or as a FIFO (first in, first out) queue, where the pool
678      * always returns the oldest object in the idle object pool.
679      *
680      * @return {@code true} if the pool is configured with LIFO behavior
681      *         or {@code false} if the pool is configured with FIFO
682      *         behavior
683      *
684      * @see #setLifo
685      */
686     public final boolean getLifo() {
687         return lifo;
688     }
689 
690     /**
691      * Gets whether this pool identifies and logs any abandoned objects.
692      *
693      * @return {@code true} if abandoned object removal is configured for this
694      *         pool and removal events are to be logged otherwise {@code false}
695      *
696      * @see AbandonedConfig#getLogAbandoned()
697      * @since 2.11.0
698      */
699     public boolean getLogAbandoned() {
700         final AbandonedConfig ac = this.abandonedConfig;
701         return ac != null && ac.getLogAbandoned();
702     }
703 
704     /**
705      * Gets the maximum time a thread has waited to borrow objects from the pool.
706      *
707      * @return maximum wait time in milliseconds since the pool was created
708      * @since 2.12.0
709      */
710     public final Duration getMaxBorrowWaitDuration() {
711         return maxBorrowWaitDuration.get();
712     }
713 
714     /**
715      * Gets the maximum time a thread has waited to borrow objects from the pool.
716      *
717      * @return maximum wait time in milliseconds since the pool was created
718      * @deprecated Use {@link #getMaxBorrowWaitDuration()}.
719      */
720     @Deprecated
721     public final long getMaxBorrowWaitTimeMillis() {
722         return maxBorrowWaitDuration.get().toMillis();
723     }
724 
725     /**
726      * Gets the maximum number of objects that can be allocated by the pool
727      * (checked out to clients, or idle awaiting checkout) at a given time. When
728      * negative, there is no limit to the number of objects that can be
729      * managed by the pool at one time.
730      *
731      * @return the cap on the total number of object instances managed by the
732      *         pool.
733      * @see #setMaxTotal
734      */
735     public final int getMaxTotal() {
736         return maxTotal;
737     }
738 
739     /**
740      * Gets the maximum duration the
741      * {@code borrowObject()} method should block before throwing an
742      * exception when the pool is exhausted and
743      * {@link #getBlockWhenExhausted} is true. When less than 0, the
744      * {@code borrowObject()} method may block indefinitely.
745      *
746      * @return the maximum number of milliseconds {@code borrowObject()}
747      *         will block.
748      *
749      * @see #setMaxWait
750      * @see #setBlockWhenExhausted
751      * @since 2.11.0
752      */
753     public final Duration getMaxWaitDuration() {
754         return maxWaitDuration;
755     }
756 
757     /**
758      * Gets the maximum amount of time (in milliseconds) the
759      * {@code borrowObject()} method should block before throwing an
760      * exception when the pool is exhausted and
761      * {@link #getBlockWhenExhausted} is true. When less than 0, the
762      * {@code borrowObject()} method may block indefinitely.
763      *
764      * @return the maximum number of milliseconds {@code borrowObject()}
765      *         will block.
766      *
767      * @see #setMaxWait
768      * @see #setBlockWhenExhausted
769      * @deprecated Use {@link #getMaxWaitDuration()}.
770      */
771     @Deprecated
772     public final long getMaxWaitMillis() {
773         return maxWaitDuration.toMillis();
774     }
775 
776     /**
777      * Gets the mean time objects are active for based on the last {@link
778      * #MEAN_TIMING_STATS_CACHE_SIZE} objects returned to the pool.
779      * @return mean time an object has been checked out from the pool among
780      * recently returned objects.
781      *
782      * @since 2.12.0
783      */
784     public final Duration getMeanActiveDuration() {
785         return activeTimes.getMeanDuration();
786     }
787 
788     /**
789      * Gets the mean time objects are active for based on the last {@link
790      * #MEAN_TIMING_STATS_CACHE_SIZE} objects returned to the pool.
791      * @return mean time an object has been checked out from the pool among
792      * recently returned objects.
793      *
794      * @deprecated Use {@link #getMeanActiveDuration()}.
795      */
796     @Deprecated
797     public final long getMeanActiveTimeMillis() {
798         return activeTimes.getMean();
799     }
800 
801     /**
802      * Gets the mean time threads wait to borrow an object based on the last {@link
803      * #MEAN_TIMING_STATS_CACHE_SIZE} objects borrowed from the pool.
804      *
805      * @return mean time in milliseconds that a recently served thread has had
806      * to wait to borrow an object from the pool.
807      * @since 2.12.0
808      */
809     public final Duration getMeanBorrowWaitDuration() {
810         return waitTimes.getMeanDuration();
811     }
812 
813     /**
814      * Gets the mean time threads wait to borrow an object based on the last {@link
815      * #MEAN_TIMING_STATS_CACHE_SIZE} objects borrowed from the pool.
816      *
817      * @return mean time in milliseconds that a recently served thread has had
818      * to wait to borrow an object from the pool.
819      * @deprecated Use {@link #getMeanBorrowWaitDuration()}.
820      */
821     @Deprecated
822     public final long getMeanBorrowWaitTimeMillis() {
823         return waitTimes.getMean();
824     }
825 
826     /**
827      * Gets the mean time objects are idle for based on the last {@link
828      * #MEAN_TIMING_STATS_CACHE_SIZE} objects borrowed from the pool.
829      *
830      * @return mean time an object has been idle in the pool among recently
831      * borrowed objects.
832      * @since 2.12.0
833      */
834     public final Duration getMeanIdleDuration() {
835         return idleTimes.getMeanDuration();
836     }
837 
838     /**
839      * Gets the mean time objects are idle for based on the last {@link
840      * #MEAN_TIMING_STATS_CACHE_SIZE} objects borrowed from the pool.
841      *
842      * @return mean time an object has been idle in the pool among recently
843      * borrowed objects.
844      * @deprecated Use {@link #getMeanIdleDuration()}.
845      */
846     @Deprecated
847     public final long getMeanIdleTimeMillis() {
848         return idleTimes.getMean();
849     }
850 
851     /**
852      * Gets whether to include statistics in exception messages.
853      * <p>
854      * 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
855      * information.
856      * </p>
857      *
858      * @return whether to include statistics in exception messages.
859      * @since 2.11.0
860      */
861     public boolean getMessageStatistics() {
862         return messageStatistics;
863     }
864 
865     /**
866      * Gets the minimum amount of time an object may sit idle in the pool
867      * before it is eligible for eviction by the idle object evictor (if any -
868      * see {@link #setDurationBetweenEvictionRuns(Duration)}). When non-positive,
869      * no objects will be evicted from the pool due to idle time alone.
870      *
871      * @return minimum amount of time an object may sit idle in the pool before
872      *         it is eligible for eviction
873      *
874      * @see #setMinEvictableIdleTimeMillis
875      * @see #setTimeBetweenEvictionRunsMillis
876      * @since 2.11.0
877      */
878     public final Duration getMinEvictableIdleDuration() {
879         return minEvictableIdleDuration;
880     }
881 
882     /**
883      * Gets the minimum amount of time an object may sit idle in the pool
884      * before it is eligible for eviction by the idle object evictor (if any -
885      * see {@link #setDurationBetweenEvictionRuns(Duration)}). When non-positive,
886      * no objects will be evicted from the pool due to idle time alone.
887      *
888      * @return minimum amount of time an object may sit idle in the pool before
889      *         it is eligible for eviction
890      *
891      * @see #setMinEvictableIdleTimeMillis
892      * @see #setTimeBetweenEvictionRunsMillis
893      * @since 2.10.0
894      * @deprecated Use {@link #getMinEvictableIdleDuration()}.
895      */
896     @Deprecated
897     public final Duration getMinEvictableIdleTime() {
898         return minEvictableIdleDuration;
899     }
900 
901     /**
902      * Gets the minimum amount of time an object may sit idle in the pool
903      * before it is eligible for eviction by the idle object evictor (if any -
904      * see {@link #setTimeBetweenEvictionRunsMillis(long)}). When non-positive,
905      * no objects will be evicted from the pool due to idle time alone.
906      *
907      * @return minimum amount of time an object may sit idle in the pool before
908      *         it is eligible for eviction
909      *
910      * @see #setMinEvictableIdleTimeMillis
911      * @see #setTimeBetweenEvictionRunsMillis
912      * @deprecated Use {@link #getMinEvictableIdleDuration()}.
913      */
914     @Deprecated
915     public final long getMinEvictableIdleTimeMillis() {
916         return minEvictableIdleDuration.toMillis();
917     }
918 
919     /**
920      * Gets the number of instances currently idle in this pool.
921      * @return count of instances available for checkout from the pool
922      */
923     public abstract int getNumIdle();
924 
925     /**
926      * Gets the maximum number of objects to examine during each run (if any)
927      * of the idle object evictor thread. When positive, the number of tests
928      * performed for a run will be the minimum of the configured value and the
929      * number of idle instances in the pool. When negative, the number of tests
930      * performed will be <code>ceil({@link #getNumIdle}/
931      * abs({@link #getNumTestsPerEvictionRun}))</code> which means that when the
932      * value is {@code -n} roughly one nth of the idle objects will be
933      * tested per run.
934      *
935      * @return max number of objects to examine during each evictor run
936      * @see #setNumTestsPerEvictionRun
937      * @see #setTimeBetweenEvictionRunsMillis
938      */
939     public final int getNumTestsPerEvictionRun() {
940         return numTestsPerEvictionRun;
941     }
942 
943     /**
944      * Gets whether a check is made for abandoned objects when an object is borrowed
945      * from this pool.
946      *
947      * @return {@code true} if abandoned object removal is configured to be
948      *         activated by borrowObject otherwise {@code false}
949      *
950      * @see AbandonedConfig#getRemoveAbandonedOnBorrow()
951      * @since 2.11.0
952      */
953     public boolean getRemoveAbandonedOnBorrow() {
954         final AbandonedConfig ac = this.abandonedConfig;
955         return ac != null && ac.getRemoveAbandonedOnBorrow();
956     }
957 
958     /**
959      * Gets whether a check is made for abandoned objects when the evictor runs.
960      *
961      * @return {@code true} if abandoned object removal is configured to be
962      *         activated when the evictor runs otherwise {@code false}
963      *
964      * @see AbandonedConfig#getRemoveAbandonedOnMaintenance()
965      * @since 2.11.0
966      */
967     public boolean getRemoveAbandonedOnMaintenance() {
968         final AbandonedConfig ac = this.abandonedConfig;
969         return ac != null && ac.getRemoveAbandonedOnMaintenance();
970     }
971 
972     /**
973      * Gets the timeout before which an object will be considered to be
974      * abandoned by this pool.
975      *
976      * @return The abandoned object timeout in seconds if abandoned object
977      *         removal is configured for this pool; Integer.MAX_VALUE otherwise.
978      *
979      * @see AbandonedConfig#getRemoveAbandonedTimeoutDuration()
980      * @see AbandonedConfig#getRemoveAbandonedTimeoutDuration()
981      * @deprecated Use {@link #getRemoveAbandonedTimeoutDuration()}.
982      * @since 2.11.0
983      */
984     @Deprecated
985     public int getRemoveAbandonedTimeout() {
986         return (int) getRemoveAbandonedTimeoutDuration().getSeconds();
987     }
988 
989     /**
990      * Gets the timeout before which an object will be considered to be
991      * abandoned by this pool.
992      *
993      * @return The abandoned object timeout in seconds if abandoned object
994      *         removal is configured for this pool; Integer.MAX_VALUE otherwise.
995      *
996      * @see AbandonedConfig#getRemoveAbandonedTimeoutDuration()
997      * @since 2.11.0
998      */
999     public Duration getRemoveAbandonedTimeoutDuration() {
1000         final AbandonedConfig ac = this.abandonedConfig;
1001         return ac != null ? ac.getRemoveAbandonedTimeoutDuration() : DEFAULT_REMOVE_ABANDONED_TIMEOUT;
1002     }
1003 
1004     /**
1005      * Gets the total number of objects returned to this pool over the lifetime of
1006      * the pool. This excludes attempts to return the same object multiple
1007      * times.
1008      * @return the returned object count
1009      */
1010     public final long getReturnedCount() {
1011         return returnedCount.get();
1012     }
1013 
1014     /**
1015      * Gets the minimum amount of time an object may sit idle in the pool
1016      * before it is eligible for eviction by the idle object evictor (if any -
1017      * see {@link #setDurationBetweenEvictionRuns(Duration)}),
1018      * with the extra condition that at least {@code minIdle} object
1019      * instances remain in the pool. This setting is overridden by
1020      * {@link #getMinEvictableIdleTime} (that is, if
1021      * {@link #getMinEvictableIdleTime} is positive, then
1022      * {@link #getSoftMinEvictableIdleTime} is ignored).
1023      *
1024      * @return minimum amount of time an object may sit idle in the pool before
1025      *         it is eligible for eviction if minIdle instances are available
1026      *
1027      * @see #setSoftMinEvictableIdleDuration(Duration)
1028      * @since 2.11.0
1029      */
1030     public final Duration getSoftMinEvictableIdleDuration() {
1031         return softMinEvictableIdleDuration;
1032     }
1033 
1034     /**
1035      * Gets the minimum amount of time an object may sit idle in the pool
1036      * before it is eligible for eviction by the idle object evictor (if any -
1037      * see {@link #setDurationBetweenEvictionRuns(Duration)}),
1038      * with the extra condition that at least {@code minIdle} object
1039      * instances remain in the pool. This setting is overridden by
1040      * {@link #getMinEvictableIdleTime} (that is, if
1041      * {@link #getMinEvictableIdleTime} is positive, then
1042      * {@link #getSoftMinEvictableIdleTime} is ignored).
1043      *
1044      * @return minimum amount of time an object may sit idle in the pool before
1045      *         it is eligible for eviction if minIdle instances are available
1046      *
1047      * @see #setSoftMinEvictableIdleDuration(Duration)
1048      * @since 2.10.0
1049      * @deprecated Use {@link #getSoftMinEvictableIdleDuration}.
1050      */
1051     @Deprecated
1052     public final Duration getSoftMinEvictableIdleTime() {
1053         return softMinEvictableIdleDuration;
1054     }
1055 
1056     /**
1057      * Gets the minimum amount of time an object may sit idle in the pool
1058      * before it is eligible for eviction by the idle object evictor (if any -
1059      * see {@link #setTimeBetweenEvictionRunsMillis(long)}),
1060      * with the extra condition that at least {@code minIdle} object
1061      * instances remain in the pool. This setting is overridden by
1062      * {@link #getMinEvictableIdleTimeMillis} (that is, if
1063      * {@link #getMinEvictableIdleTimeMillis} is positive, then
1064      * {@link #getSoftMinEvictableIdleTimeMillis} is ignored).
1065      *
1066      * @return minimum amount of time an object may sit idle in the pool before
1067      *         it is eligible for eviction if minIdle instances are available
1068      *
1069      * @see #setSoftMinEvictableIdleTimeMillis
1070      * @deprecated Use {@link #getSoftMinEvictableIdleTime()}.
1071      */
1072     @Deprecated
1073     public final long getSoftMinEvictableIdleTimeMillis() {
1074         return softMinEvictableIdleDuration.toMillis();
1075     }
1076 
1077     /**
1078      * Gets the stack trace of an exception as a string.
1079      * @param e exception to trace
1080      * @return exception stack trace as a string
1081      */
1082     private String getStackTrace(final Exception e) {
1083         // Need the exception in string form to prevent the retention of
1084         // references to classes in the stack trace that could trigger a memory
1085         // leak in a container environment.
1086         final Writer w = new StringWriter();
1087         final PrintWriter pw = new PrintWriter(w);
1088         e.printStackTrace(pw);
1089         return w.toString();
1090     }
1091 
1092     /**
1093      * Gets a statistics string.
1094      *
1095      * @return  a statistics string.
1096      */
1097     String getStatsString() {
1098         // Simply listed in AB order.
1099         return String.format(
1100                 "activeTimes=%s, blockWhenExhausted=%s, borrowedCount=%,d, closed=%s, createdCount=%,d, destroyedByBorrowValidationCount=%,d, " +
1101                         "destroyedByEvictorCount=%,d, evictorShutdownTimeoutDuration=%s, fairness=%s, idleTimes=%s, lifo=%s, maxBorrowWaitDuration=%s, " +
1102                         "maxTotal=%s, maxWaitDuration=%s, minEvictableIdleDuration=%s, numTestsPerEvictionRun=%s, returnedCount=%s, " +
1103                         "softMinEvictableIdleDuration=%s, testOnBorrow=%s, testOnCreate=%s, testOnReturn=%s, testWhileIdle=%s, " +
1104                         "durationBetweenEvictionRuns=%s, waitTimes=%s",
1105                 activeTimes.getValues(), blockWhenExhausted, borrowedCount.get(), closed, createdCount.get(), destroyedByBorrowValidationCount.get(),
1106                 destroyedByEvictorCount.get(), evictorShutdownTimeoutDuration, fairness, idleTimes.getValues(), lifo, maxBorrowWaitDuration.get(),
1107                 maxTotal, maxWaitDuration, minEvictableIdleDuration, numTestsPerEvictionRun, returnedCount, softMinEvictableIdleDuration, testOnBorrow,
1108                 testOnCreate, testOnReturn, testWhileIdle, durationBetweenEvictionRuns, waitTimes.getValues());
1109     }
1110 
1111     /**
1112      * Gets the listener used (if any) to receive notifications of exceptions
1113      * unavoidably swallowed by the pool.
1114      *
1115      * @return The listener or {@code null} for no listener
1116      */
1117     public final SwallowedExceptionListener getSwallowedExceptionListener() {
1118         return swallowedExceptionListener;
1119     }
1120 
1121     /**
1122      * Gets whether objects borrowed from the pool will be validated before
1123      * being returned from the {@code borrowObject()} method. Validation is
1124      * performed by the {@code validateObject()} method of the factory
1125      * associated with the pool. If the object fails to validate, it will be
1126      * removed from the pool and destroyed, and a new attempt will be made to
1127      * borrow an object from the pool.
1128      *
1129      * @return {@code true} if objects are validated before being returned
1130      *         from the {@code borrowObject()} method
1131      *
1132      * @see #setTestOnBorrow
1133      */
1134     public final boolean getTestOnBorrow() {
1135         return testOnBorrow;
1136     }
1137 
1138     /**
1139      * Gets whether objects created for the pool will be validated before
1140      * being returned from the {@code borrowObject()} method. Validation is
1141      * performed by the {@code validateObject()} method of the factory
1142      * associated with the pool. If the object fails to validate, then
1143      * {@code borrowObject()} will fail.
1144      *
1145      * @return {@code true} if newly created objects are validated before
1146      *         being returned from the {@code borrowObject()} method
1147      *
1148      * @see #setTestOnCreate
1149      * @since 2.2
1150      */
1151     public final boolean getTestOnCreate() {
1152         return testOnCreate;
1153     }
1154 
1155     /**
1156      * Gets whether objects borrowed from the pool will be validated when
1157      * they are returned to the pool via the {@code returnObject()} method.
1158      * Validation is performed by the {@code validateObject()} method of
1159      * the factory associated with the pool. Returning objects that fail validation
1160      * are destroyed rather then being returned the pool.
1161      *
1162      * @return {@code true} if objects are validated on return to
1163      *         the pool via the {@code returnObject()} method
1164      *
1165      * @see #setTestOnReturn
1166      */
1167     public final boolean getTestOnReturn() {
1168         return testOnReturn;
1169     }
1170 
1171     /**
1172      * Gets whether objects sitting idle in the pool will be validated by the
1173      * idle object evictor (if any - see
1174      * {@link #setDurationBetweenEvictionRuns(Duration)}). Validation is performed
1175      * by the {@code validateObject()} method of the factory associated
1176      * with the pool. If the object fails to validate, it will be removed from
1177      * the pool and destroyed.
1178      *
1179      * @return {@code true} if objects will be validated by the evictor
1180      * @see #setTestWhileIdle
1181      * @see #setTimeBetweenEvictionRunsMillis
1182      */
1183     public final boolean getTestWhileIdle() {
1184         return testWhileIdle;
1185     }
1186 
1187     /**
1188      * Gets the duration to sleep between runs of the idle
1189      * object evictor thread. When non-positive, no idle object evictor thread
1190      * will be run.
1191      *
1192      * @return number of milliseconds to sleep between evictor runs
1193      * @see #setTimeBetweenEvictionRuns
1194      * @since 2.10.0
1195      * @deprecated {@link #getDurationBetweenEvictionRuns()}.
1196      */
1197     @Deprecated
1198     public final Duration getTimeBetweenEvictionRuns() {
1199         return durationBetweenEvictionRuns;
1200     }
1201 
1202     /**
1203      * Gets the number of milliseconds to sleep between runs of the idle
1204      * object evictor thread. When non-positive, no idle object evictor thread
1205      * will be run.
1206      *
1207      * @return number of milliseconds to sleep between evictor runs
1208      * @see #setTimeBetweenEvictionRunsMillis
1209      * @deprecated Use {@link #getDurationBetweenEvictionRuns()}.
1210      */
1211     @Deprecated
1212     public final long getTimeBetweenEvictionRunsMillis() {
1213         return durationBetweenEvictionRuns.toMillis();
1214     }
1215 
1216     /**
1217      * Tests whether or not abandoned object removal is configured for this pool.
1218      *
1219      * @return true if this pool is configured to detect and remove
1220      * abandoned objects
1221      * @since 2.11.0
1222      */
1223     public boolean isAbandonedConfig() {
1224         return abandonedConfig != null;
1225     }
1226 
1227     /**
1228      * Tests whether this pool instance been closed.
1229      * @return {@code true} when this pool has been closed.
1230      */
1231     public final boolean isClosed() {
1232         return closed;
1233     }
1234 
1235     /**
1236      * Registers the pool with the platform MBean server.
1237      * The registered name will be
1238      * {@code jmxNameBase + jmxNamePrefix + i} where i is the least
1239      * integer greater than or equal to 1 such that the name is not already
1240      * registered. Swallows MBeanRegistrationException, NotCompliantMBeanException
1241      * returning null.
1242      *
1243      * @param config Pool configuration
1244      * @param jmxNameBase default base JMX name for this pool
1245      * @param jmxNamePrefix name prefix
1246      * @return registered ObjectName, null if registration fails
1247      */
1248     private ObjectName jmxRegister(final BaseObjectPoolConfig<T> config,
1249             final String jmxNameBase, String jmxNamePrefix) {
1250         ObjectName newObjectName = null;
1251         final MBeanServer mbs = ManagementFactory.getPlatformMBeanServer();
1252         int i = 1;
1253         boolean registered = false;
1254         String base = config.getJmxNameBase();
1255         if (base == null) {
1256             base = jmxNameBase;
1257         }
1258         while (!registered) {
1259             try {
1260                 ObjectName objName;
1261                 // Skip the numeric suffix for the first pool in case there is
1262                 // only one so the names are cleaner.
1263                 if (i == 1) {
1264                     objName = new ObjectName(base + jmxNamePrefix);
1265                 } else {
1266                     objName = new ObjectName(base + jmxNamePrefix + i);
1267                 }
1268                 if (!mbs.isRegistered(objName)) {
1269                     mbs.registerMBean(this, objName);
1270                     newObjectName = objName;
1271                     registered = true;
1272                 } else {
1273                     // Increment the index and try again
1274                     i++;
1275                 }
1276             } catch (final MalformedObjectNameException e) {
1277                 if (BaseObjectPoolConfig.DEFAULT_JMX_NAME_PREFIX.equals(
1278                         jmxNamePrefix) && jmxNameBase.equals(base)) {
1279                     // Shouldn't happen. Skip registration if it does.
1280                     registered = true;
1281                 } else {
1282                     // Must be an invalid name. Use the defaults instead.
1283                     jmxNamePrefix =
1284                             BaseObjectPoolConfig.DEFAULT_JMX_NAME_PREFIX;
1285                     base = jmxNameBase;
1286                 }
1287             } catch (final InstanceAlreadyExistsException e) {
1288                 // Increment the index and try again
1289                 i++;
1290             } catch (final MBeanRegistrationException | NotCompliantMBeanException e) {
1291                 // Shouldn't happen. Skip registration if it does.
1292                 registered = true;
1293             }
1294         }
1295         return newObjectName;
1296     }
1297 
1298     /**
1299      * Unregisters this pool's MBean.
1300      */
1301     final void jmxUnregister() {
1302         if (objectName != null) {
1303             try {
1304                 ManagementFactory.getPlatformMBeanServer().unregisterMBean(objectName);
1305             } catch (final MBeanRegistrationException | InstanceNotFoundException e) {
1306                 swallowException(e);
1307             }
1308         }
1309     }
1310 
1311     /**
1312      * Marks the object as returning to the pool.
1313      * @param pooledObject instance to return to the keyed pool
1314      */
1315     protected void markReturningState(final PooledObject<T> pooledObject) {
1316         synchronized (pooledObject) {
1317             if (pooledObject.getState() != PooledObjectState.ALLOCATED) {
1318                 throw new IllegalStateException("Object has already been returned to this pool or is invalid");
1319             }
1320             pooledObject.markReturning(); // Keep from being marked abandoned
1321         }
1322     }
1323 
1324     /**
1325      * Sets the abandoned object removal configuration.
1326      *
1327      * @param abandonedConfig the new configuration to use. This is used by value.
1328      * @see AbandonedConfig
1329      * @since 2.11.0
1330      */
1331     public void setAbandonedConfig(final AbandonedConfig abandonedConfig) {
1332         this.abandonedConfig = AbandonedConfig.copy(abandonedConfig);
1333     }
1334 
1335     /**
1336      * Sets whether to block when the {@code borrowObject()} method is
1337      * invoked when the pool is exhausted (the maximum number of "active"
1338      * objects has been reached).
1339      *
1340      * @param blockWhenExhausted    {@code true} if
1341      *                              {@code borrowObject()} should block
1342      *                              when the pool is exhausted
1343      *
1344      * @see #getBlockWhenExhausted
1345      */
1346     public final void setBlockWhenExhausted(final boolean blockWhenExhausted) {
1347         this.blockWhenExhausted = blockWhenExhausted;
1348     }
1349 
1350     /**
1351      * Sets the receiver with the given configuration.
1352      *
1353      * @param config Initialization source.
1354      */
1355     protected void setConfig(final BaseObjectPoolConfig<T> config) {
1356         setLifo(config.getLifo());
1357         setMaxWait(config.getMaxWaitDuration());
1358         setBlockWhenExhausted(config.getBlockWhenExhausted());
1359         setTestOnCreate(config.getTestOnCreate());
1360         setTestOnBorrow(config.getTestOnBorrow());
1361         setTestOnReturn(config.getTestOnReturn());
1362         setTestWhileIdle(config.getTestWhileIdle());
1363         setNumTestsPerEvictionRun(config.getNumTestsPerEvictionRun());
1364         setMinEvictableIdleDuration(config.getMinEvictableIdleDuration());
1365         setDurationBetweenEvictionRuns(config.getDurationBetweenEvictionRuns());
1366         setSoftMinEvictableIdleDuration(config.getSoftMinEvictableIdleDuration());
1367         final EvictionPolicy<T> policy = config.getEvictionPolicy();
1368         if (policy == null) {
1369             // Use the class name (pre-2.6.0 compatible)
1370             setEvictionPolicyClassName(config.getEvictionPolicyClassName());
1371         } else {
1372             // Otherwise, use the class (2.6.0 feature)
1373             setEvictionPolicy(policy);
1374         }
1375         setEvictorShutdownTimeout(config.getEvictorShutdownTimeoutDuration());
1376     }
1377 
1378     /**
1379      * Sets the number of milliseconds to sleep between runs of the idle object evictor thread.
1380      * <ul>
1381      * <li>When positive, the idle object evictor thread starts.</li>
1382      * <li>When null or non-positive, no idle object evictor thread runs.</li>
1383      * </ul>
1384      *
1385      * @param timeBetweenEvictionRuns
1386      *            duration to sleep between evictor runs
1387      *
1388      * @see #getDurationBetweenEvictionRuns()
1389      * @since 2.12.0
1390      */
1391     public final void setDurationBetweenEvictionRuns(final Duration timeBetweenEvictionRuns) {
1392         this.durationBetweenEvictionRuns = PoolImplUtils.nonNull(timeBetweenEvictionRuns, BaseObjectPoolConfig.DEFAULT_DURATION_BETWEEN_EVICTION_RUNS);
1393         startEvictor(this.durationBetweenEvictionRuns);
1394     }
1395 
1396     /**
1397      * Sets the eviction policy for this pool.
1398      *
1399      * @param evictionPolicy
1400      *            the eviction policy for this pool.
1401      * @since 2.6.0
1402      */
1403     public void setEvictionPolicy(final EvictionPolicy<T> evictionPolicy) {
1404         this.evictionPolicy = evictionPolicy;
1405     }
1406 
1407     /**
1408      * Sets the eviction policy.
1409      *
1410      * @param className Eviction policy class name.
1411      * @param classLoader Load the class from this class loader.
1412      * @throws LinkageError if the linkage fails
1413      * @throws ExceptionInInitializerError if the initialization provoked by this method fails
1414      * @throws ClassNotFoundException if the class cannot be located by the specified class loader
1415      * @throws IllegalAccessException if this {@code Constructor} object is enforcing Java language access control and the underlying constructor is
1416      *         inaccessible.
1417      * @throws IllegalArgumentException if the number of actual and formal parameters differ; if an unwrapping conversion for primitive arguments fails; or if,
1418      *         after possible unwrapping, a parameter value cannot be converted to the corresponding formal parameter type by a method invocation conversion; if
1419      *         this constructor pertains to an enum type.
1420      * @throws InstantiationException if the class that declares the underlying constructor represents an abstract class.
1421      * @throws InvocationTargetException if the underlying constructor throws an exception.
1422      * @throws ExceptionInInitializerError if the initialization provoked by this method fails.
1423      * @throws NoSuchMethodException if a matching method is not found.
1424      * @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
1425      *         current class and invocation of {@link SecurityManager#checkPackageAccess s.checkPackageAccess()} denies access to the package of this class.
1426      */
1427     @SuppressWarnings("unchecked")
1428     private void setEvictionPolicy(final String className, final ClassLoader classLoader)
1429             throws ClassNotFoundException, InstantiationException, IllegalAccessException, InvocationTargetException, NoSuchMethodException {
1430         final Class<?> clazz = Class.forName(className, true, classLoader);
1431         final Object policy = clazz.getConstructor().newInstance();
1432         this.evictionPolicy = (EvictionPolicy<T>) policy;
1433     }
1434 
1435     /**
1436      * Sets the name of the {@link EvictionPolicy} implementation that is used by this pool. The Pool will attempt to
1437      * load the class using the thread context class loader. If that fails, the use the class loader for the
1438      * {@link EvictionPolicy} interface.
1439      *
1440      * @param evictionPolicyClassName
1441      *            the fully qualified class name of the new eviction policy
1442      *
1443      * @see #getEvictionPolicyClassName()
1444      * @since 2.6.0 If loading the class using the thread context class loader fails, use the class loader for the
1445      *        {@link EvictionPolicy} interface.
1446      */
1447     public final void setEvictionPolicyClassName(final String evictionPolicyClassName) {
1448         setEvictionPolicyClassName(evictionPolicyClassName, Thread.currentThread().getContextClassLoader());
1449     }
1450 
1451     /**
1452      * Sets the name of the {@link EvictionPolicy} implementation that is used by this pool. The Pool will attempt to
1453      * load the class using the given class loader. If that fails, use the class loader for the {@link EvictionPolicy}
1454      * interface.
1455      *
1456      * @param evictionPolicyClassName
1457      *            the fully qualified class name of the new eviction policy
1458      * @param classLoader
1459      *            the class loader to load the given {@code evictionPolicyClassName}.
1460      *
1461      * @see #getEvictionPolicyClassName()
1462      * @since 2.6.0 If loading the class using the given class loader fails, use the class loader for the
1463      *        {@link EvictionPolicy} interface.
1464      */
1465     public final void setEvictionPolicyClassName(final String evictionPolicyClassName, final ClassLoader classLoader) {
1466         // Getting epClass here and now best matches the caller's environment
1467         final Class<?> epClass = EvictionPolicy.class;
1468         final ClassLoader epClassLoader = epClass.getClassLoader();
1469         try {
1470             try {
1471                 setEvictionPolicy(evictionPolicyClassName, classLoader);
1472             } catch (final ClassCastException | ClassNotFoundException e) {
1473                 setEvictionPolicy(evictionPolicyClassName, epClassLoader);
1474             }
1475         } catch (final ClassCastException e) {
1476             throw new IllegalArgumentException("Class " + evictionPolicyClassName + " from class loaders [" +
1477                     classLoader + ", " + epClassLoader + "] do not implement " + EVICTION_POLICY_TYPE_NAME);
1478         } catch (final ClassNotFoundException | InstantiationException | IllegalAccessException |
1479                 InvocationTargetException | NoSuchMethodException e) {
1480             throw new IllegalArgumentException(
1481                     "Unable to create " + EVICTION_POLICY_TYPE_NAME + " instance of type " + evictionPolicyClassName,
1482                     e);
1483         }
1484     }
1485 
1486     /**
1487      * Sets the timeout that will be used when waiting for the Evictor to shutdown if this pool is closed and it is the
1488      * only pool still using the value for the Evictor.
1489      *
1490      * @param evictorShutdownTimeout the timeout in milliseconds that will be used while waiting for the Evictor
1491      *                                     to shut down.
1492      * @since 2.10.0
1493      */
1494     public final void setEvictorShutdownTimeout(final Duration evictorShutdownTimeout) {
1495         this.evictorShutdownTimeoutDuration = PoolImplUtils.nonNull(evictorShutdownTimeout, BaseObjectPoolConfig.DEFAULT_EVICTOR_SHUTDOWN_TIMEOUT);
1496     }
1497 
1498     /**
1499      * Sets the timeout that will be used when waiting for the Evictor to shutdown if this pool is closed and it is the
1500      * only pool still using the value for the Evictor.
1501      *
1502      * @param evictorShutdownTimeoutMillis the timeout in milliseconds that will be used while waiting for the Evictor
1503      *                                     to shut down.
1504      * @deprecated Use {@link #setEvictorShutdownTimeout(Duration)}.
1505      */
1506     @Deprecated
1507     public final void setEvictorShutdownTimeoutMillis(final long evictorShutdownTimeoutMillis) {
1508         setEvictorShutdownTimeout(Duration.ofMillis(evictorShutdownTimeoutMillis));
1509     }
1510 
1511     /**
1512      * Sets whether the pool has LIFO (last in, first out) behavior with
1513      * respect to idle objects - always returning the most recently used object
1514      * from the pool, or as a FIFO (first in, first out) queue, where the pool
1515      * always returns the oldest object in the idle object pool.
1516      *
1517      * @param lifo  {@code true} if the pool is to be configured with LIFO
1518      *              behavior or {@code false} if the pool is to be
1519      *              configured with FIFO behavior
1520      *
1521      * @see #getLifo()
1522      */
1523     public final void setLifo(final boolean lifo) {
1524         this.lifo = lifo;
1525     }
1526 
1527     /**
1528      * Sets the cap on the number of objects that can be allocated by the pool
1529      * (checked out to clients, or idle awaiting checkout) at a given time. Use
1530      * a negative value for no limit.
1531      *
1532      * @param maxTotal  The cap on the total number of object instances managed
1533      *                  by the pool. Negative values mean that there is no limit
1534      *                  to the number of objects allocated by the pool.
1535      *
1536      * @see #getMaxTotal
1537      */
1538     public final void setMaxTotal(final int maxTotal) {
1539         this.maxTotal = maxTotal;
1540     }
1541 
1542     /**
1543      * Sets the maximum duration the
1544      * {@code borrowObject()} method should block before throwing an
1545      * exception when the pool is exhausted and
1546      * {@link #getBlockWhenExhausted} is true. When less than 0, the
1547      * {@code borrowObject()} method may block indefinitely.
1548      *
1549      * @param maxWaitDuration the maximum duration
1550      *                      {@code borrowObject()} will block or negative
1551      *                      for indefinitely.
1552      *
1553      * @see #getMaxWaitDuration
1554      * @see #setBlockWhenExhausted
1555      * @since 2.11.0
1556      */
1557     public final void setMaxWait(final Duration maxWaitDuration) {
1558         this.maxWaitDuration = PoolImplUtils.nonNull(maxWaitDuration, BaseObjectPoolConfig.DEFAULT_MAX_WAIT);
1559     }
1560 
1561     /**
1562      * Sets the maximum amount of time (in milliseconds) the
1563      * {@code borrowObject()} method should block before throwing an
1564      * exception when the pool is exhausted and
1565      * {@link #getBlockWhenExhausted} is true. When less than 0, the
1566      * {@code borrowObject()} method may block indefinitely.
1567      *
1568      * @param maxWaitMillis the maximum number of milliseconds
1569      *                      {@code borrowObject()} will block or negative
1570      *                      for indefinitely.
1571      *
1572      * @see #getMaxWaitDuration
1573      * @see #setBlockWhenExhausted
1574      * @deprecated Use {@link #setMaxWait}.
1575      */
1576     @Deprecated
1577     public final void setMaxWaitMillis(final long maxWaitMillis) {
1578         setMaxWait(Duration.ofMillis(maxWaitMillis));
1579     }
1580 
1581     /**
1582      * Sets whether to include statistics in exception messages.
1583      * <p>
1584      * 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
1585      * information.
1586      * </p>
1587      *
1588      * @param messagesDetails whether to include statistics in exception messages.
1589      * @since 2.11.0
1590      */
1591     public void setMessagesStatistics(final boolean messagesDetails) {
1592         this.messageStatistics = messagesDetails;
1593     }
1594 
1595     /**
1596      * Sets the minimum amount of time an object may sit idle in the pool
1597      * before it is eligible for eviction by the idle object evictor (if any -
1598      * see {@link #setDurationBetweenEvictionRuns(Duration)}). When non-positive,
1599      * no objects will be evicted from the pool due to idle time alone.
1600      *
1601      * @param minEvictableIdleTime
1602      *            minimum amount of time an object may sit idle in the pool
1603      *            before it is eligible for eviction
1604      *
1605      * @see #getMinEvictableIdleTime
1606      * @see #setTimeBetweenEvictionRuns
1607      * @since 2.11.0
1608      * @deprecated Use {@link #setMinEvictableIdleDuration(Duration)}.
1609      */
1610     @Deprecated
1611     public final void setMinEvictableIdle(final Duration minEvictableIdleTime) {
1612         this.minEvictableIdleDuration = PoolImplUtils.nonNull(minEvictableIdleTime, BaseObjectPoolConfig.DEFAULT_MIN_EVICTABLE_IDLE_DURATION);
1613     }
1614 
1615     /**
1616      * Sets the minimum amount of time an object may sit idle in the pool
1617      * before it is eligible for eviction by the idle object evictor (if any -
1618      * see {@link #setDurationBetweenEvictionRuns(Duration)}). When non-positive,
1619      * no objects will be evicted from the pool due to idle time alone.
1620      *
1621      * @param minEvictableIdleTime
1622      *            minimum amount of time an object may sit idle in the pool
1623      *            before it is eligible for eviction
1624      *
1625      * @see #getMinEvictableIdleTime
1626      * @see #setTimeBetweenEvictionRuns
1627      * @since 2.12.0
1628      */
1629     public final void setMinEvictableIdleDuration(final Duration minEvictableIdleTime) {
1630         this.minEvictableIdleDuration = PoolImplUtils.nonNull(minEvictableIdleTime, BaseObjectPoolConfig.DEFAULT_MIN_EVICTABLE_IDLE_DURATION);
1631     }
1632 
1633     /**
1634      * Sets the minimum amount of time an object may sit idle in the pool
1635      * before it is eligible for eviction by the idle object evictor (if any -
1636      * see {@link #setDurationBetweenEvictionRuns(Duration)}). When non-positive,
1637      * no objects will be evicted from the pool due to idle time alone.
1638      *
1639      * @param minEvictableIdleTime
1640      *            minimum amount of time an object may sit idle in the pool
1641      *            before it is eligible for eviction
1642      *
1643      * @see #getMinEvictableIdleTime
1644      * @see #setTimeBetweenEvictionRuns
1645      * @since 2.10.0
1646      * @deprecated Use {@link #setMinEvictableIdleDuration(Duration)}.
1647      */
1648     @Deprecated
1649     public final void setMinEvictableIdleTime(final Duration minEvictableIdleTime) {
1650         this.minEvictableIdleDuration = PoolImplUtils.nonNull(minEvictableIdleTime, BaseObjectPoolConfig.DEFAULT_MIN_EVICTABLE_IDLE_DURATION);
1651     }
1652 
1653     /**
1654      * Sets the minimum amount of time an object may sit idle in the pool
1655      * before it is eligible for eviction by the idle object evictor (if any -
1656      * see {@link #setTimeBetweenEvictionRunsMillis(long)}). When non-positive,
1657      * no objects will be evicted from the pool due to idle time alone.
1658      *
1659      * @param minEvictableIdleTimeMillis
1660      *            minimum amount of time an object may sit idle in the pool
1661      *            before it is eligible for eviction
1662      *
1663      * @see #getMinEvictableIdleTimeMillis
1664      * @see #setTimeBetweenEvictionRunsMillis
1665      * @deprecated Use {@link #setMinEvictableIdleTime(Duration)}.
1666      */
1667     @Deprecated
1668     public final void setMinEvictableIdleTimeMillis(final long minEvictableIdleTimeMillis) {
1669         setMinEvictableIdleTime(Duration.ofMillis(minEvictableIdleTimeMillis));
1670     }
1671 
1672     /**
1673      * Sets the maximum number of objects to examine during each run (if any)
1674      * of the idle object evictor thread. When positive, the number of tests
1675      * performed for a run will be the minimum of the configured value and the
1676      * number of idle instances in the pool. When negative, the number of tests
1677      * performed will be <code>ceil({@link #getNumIdle}/
1678      * abs({@link #getNumTestsPerEvictionRun}))</code> which means that when the
1679      * value is {@code -n} roughly one nth of the idle objects will be
1680      * tested per run.
1681      *
1682      * @param numTestsPerEvictionRun
1683      *            max number of objects to examine during each evictor run
1684      *
1685      * @see #getNumTestsPerEvictionRun
1686      * @see #setTimeBetweenEvictionRunsMillis
1687      */
1688     public final void setNumTestsPerEvictionRun(final int numTestsPerEvictionRun) {
1689         this.numTestsPerEvictionRun = numTestsPerEvictionRun;
1690     }
1691 
1692     /**
1693      * Sets the minimum amount of time an object may sit idle in the pool
1694      * before it is eligible for eviction by the idle object evictor (if any -
1695      * see {@link #setDurationBetweenEvictionRuns(Duration)}),
1696      * with the extra condition that at least {@code minIdle} object
1697      * instances remain in the pool. This setting is overridden by
1698      * {@link #getMinEvictableIdleTime} (that is, if
1699      * {@link #getMinEvictableIdleTime} is positive, then
1700      * {@link #getSoftMinEvictableIdleTime} is ignored).
1701      *
1702      * @param softMinEvictableIdleTime
1703      *            minimum amount of time an object may sit idle in the pool
1704      *            before it is eligible for eviction if minIdle instances are
1705      *            available
1706      *
1707      * @see #getSoftMinEvictableIdleTimeMillis
1708      * @since 2.11.0
1709      * @deprecated Use {@link #setSoftMinEvictableIdleDuration(Duration)}.
1710      */
1711     @Deprecated
1712     public final void setSoftMinEvictableIdle(final Duration softMinEvictableIdleTime) {
1713         this.softMinEvictableIdleDuration = PoolImplUtils.nonNull(softMinEvictableIdleTime, BaseObjectPoolConfig.DEFAULT_SOFT_MIN_EVICTABLE_IDLE_DURATION);
1714     }
1715 
1716     /**
1717      * Sets the minimum amount of time an object may sit idle in the pool
1718      * before it is eligible for eviction by the idle object evictor (if any -
1719      * see {@link #setDurationBetweenEvictionRuns(Duration)}),
1720      * with the extra condition that at least {@code minIdle} object
1721      * instances remain in the pool. This setting is overridden by
1722      * {@link #getMinEvictableIdleTime} (that is, if
1723      * {@link #getMinEvictableIdleTime} is positive, then
1724      * {@link #getSoftMinEvictableIdleTime} is ignored).
1725      *
1726      * @param softMinEvictableIdleTime
1727      *            minimum amount of time an object may sit idle in the pool
1728      *            before it is eligible for eviction if minIdle instances are
1729      *            available
1730      *
1731      * @see #getSoftMinEvictableIdleTimeMillis
1732      * @since 2.12.0
1733      */
1734     public final void setSoftMinEvictableIdleDuration(final Duration softMinEvictableIdleTime) {
1735         this.softMinEvictableIdleDuration = PoolImplUtils.nonNull(softMinEvictableIdleTime, BaseObjectPoolConfig.DEFAULT_SOFT_MIN_EVICTABLE_IDLE_DURATION);
1736     }
1737 
1738     /**
1739      * Sets the minimum amount of time an object may sit idle in the pool
1740      * before it is eligible for eviction by the idle object evictor (if any -
1741      * see {@link #setDurationBetweenEvictionRuns(Duration)}),
1742      * with the extra condition that at least {@code minIdle} object
1743      * instances remain in the pool. This setting is overridden by
1744      * {@link #getMinEvictableIdleTime} (that is, if
1745      * {@link #getMinEvictableIdleTime} is positive, then
1746      * {@link #getSoftMinEvictableIdleTime} is ignored).
1747      *
1748      * @param softMinEvictableIdleTime
1749      *            minimum amount of time an object may sit idle in the pool
1750      *            before it is eligible for eviction if minIdle instances are
1751      *            available
1752      *
1753      * @see #getSoftMinEvictableIdleTimeMillis
1754      * @since 2.10.0
1755      * @deprecated Use {@link #setSoftMinEvictableIdleDuration(Duration)}.
1756      */
1757     @Deprecated
1758     public final void setSoftMinEvictableIdleTime(final Duration softMinEvictableIdleTime) {
1759         this.softMinEvictableIdleDuration = PoolImplUtils.nonNull(softMinEvictableIdleTime, BaseObjectPoolConfig.DEFAULT_SOFT_MIN_EVICTABLE_IDLE_DURATION);
1760     }
1761 
1762     /**
1763      * Sets the minimum amount of time an object may sit idle in the pool
1764      * before it is eligible for eviction by the idle object evictor (if any -
1765      * see {@link #setTimeBetweenEvictionRunsMillis(long)}),
1766      * with the extra condition that at least {@code minIdle} object
1767      * instances remain in the pool. This setting is overridden by
1768      * {@link #getMinEvictableIdleTimeMillis} (that is, if
1769      * {@link #getMinEvictableIdleTimeMillis} is positive, then
1770      * {@link #getSoftMinEvictableIdleTimeMillis} is ignored).
1771      *
1772      * @param softMinEvictableIdleTimeMillis
1773      *            minimum amount of time an object may sit idle in the pool
1774      *            before it is eligible for eviction if minIdle instances are
1775      *            available
1776      *
1777      * @see #getSoftMinEvictableIdleTimeMillis
1778      * @deprecated Use {@link #setSoftMinEvictableIdleDuration(Duration)}.
1779      */
1780     @Deprecated
1781     public final void setSoftMinEvictableIdleTimeMillis(final long softMinEvictableIdleTimeMillis) {
1782         setSoftMinEvictableIdleTime(Duration.ofMillis(softMinEvictableIdleTimeMillis));
1783     }
1784 
1785     /**
1786      * Sets the listener used (if any) to receive notifications of exceptions
1787      * unavoidably swallowed by the pool.
1788      *
1789      * @param swallowedExceptionListener    The listener or {@code null}
1790      *                                      for no listener
1791      */
1792     public final void setSwallowedExceptionListener(
1793             final SwallowedExceptionListener swallowedExceptionListener) {
1794         this.swallowedExceptionListener = swallowedExceptionListener;
1795     }
1796 
1797     /**
1798      * Sets whether objects borrowed from the pool will be validated before
1799      * being returned from the {@code borrowObject()} method. Validation is
1800      * performed by the {@code validateObject()} method of the factory
1801      * associated with the pool. If the object fails to validate, it will be
1802      * removed from the pool and destroyed, and a new attempt will be made to
1803      * borrow an object from the pool.
1804      *
1805      * @param testOnBorrow  {@code true} if objects should be validated
1806      *                      before being returned from the
1807      *                      {@code borrowObject()} method
1808      *
1809      * @see #getTestOnBorrow
1810      */
1811     public final void setTestOnBorrow(final boolean testOnBorrow) {
1812         this.testOnBorrow = testOnBorrow;
1813     }
1814 
1815     /**
1816      * Sets whether objects created for the pool will be validated before
1817      * being returned from the {@code borrowObject()} method. Validation is
1818      * performed by the {@code validateObject()} method of the factory
1819      * associated with the pool. If the object fails to validate, then
1820      * {@code borrowObject()} will fail.
1821      *
1822      * @param testOnCreate  {@code true} if newly created objects should be
1823      *                      validated before being returned from the
1824      *                      {@code borrowObject()} method
1825      *
1826      * @see #getTestOnCreate
1827      * @since 2.2
1828      */
1829     public final void setTestOnCreate(final boolean testOnCreate) {
1830         this.testOnCreate = testOnCreate;
1831     }
1832 
1833     /**
1834      * Sets whether objects borrowed from the pool will be validated when
1835      * they are returned to the pool via the {@code returnObject()} method.
1836      * Validation is performed by the {@code validateObject()} method of
1837      * the factory associated with the pool. Returning objects that fail validation
1838      * are destroyed rather then being returned the pool.
1839      *
1840      * @param testOnReturn {@code true} if objects are validated on
1841      *                     return to the pool via the
1842      *                     {@code returnObject()} method
1843      *
1844      * @see #getTestOnReturn
1845      */
1846     public final void setTestOnReturn(final boolean testOnReturn) {
1847         this.testOnReturn = testOnReturn;
1848     }
1849 
1850     /**
1851      * Sets whether objects sitting idle in the pool will be validated by the
1852      * idle object evictor (if any - see
1853      * {@link #setDurationBetweenEvictionRuns(Duration)}). Validation is performed
1854      * by the {@code validateObject()} method of the factory associated
1855      * with the pool. If the object fails to validate, it will be removed from
1856      * the pool and destroyed.  Note that setting this property has no effect
1857      * unless the idle object evictor is enabled by setting
1858      * {@code timeBetweenEvictionRunsMillis} to a positive value.
1859      *
1860      * @param testWhileIdle
1861      *            {@code true} so objects will be validated by the evictor
1862      *
1863      * @see #getTestWhileIdle
1864      * @see #setTimeBetweenEvictionRuns
1865      */
1866     public final void setTestWhileIdle(final boolean testWhileIdle) {
1867         this.testWhileIdle = testWhileIdle;
1868     }
1869 
1870     /**
1871      * Sets the number of milliseconds to sleep between runs of the idle object evictor thread.
1872      * <ul>
1873      * <li>When positive, the idle object evictor thread starts.</li>
1874      * <li>When non-positive, no idle object evictor thread runs.</li>
1875      * </ul>
1876      *
1877      * @param timeBetweenEvictionRuns
1878      *            duration to sleep between evictor runs
1879      *
1880      * @see #getDurationBetweenEvictionRuns()
1881      * @since 2.10.0
1882      * @deprecated Use {@link #setDurationBetweenEvictionRuns(Duration)}.
1883      */
1884     @Deprecated
1885     public final void setTimeBetweenEvictionRuns(final Duration timeBetweenEvictionRuns) {
1886         this.durationBetweenEvictionRuns = PoolImplUtils.nonNull(timeBetweenEvictionRuns, BaseObjectPoolConfig.DEFAULT_DURATION_BETWEEN_EVICTION_RUNS);
1887         startEvictor(this.durationBetweenEvictionRuns);
1888     }
1889 
1890     /**
1891      * Sets the number of milliseconds to sleep between runs of the idle object evictor thread.
1892      * <ul>
1893      * <li>When positive, the idle object evictor thread starts.</li>
1894      * <li>When non-positive, no idle object evictor thread runs.</li>
1895      * </ul>
1896      *
1897      * @param timeBetweenEvictionRunsMillis
1898      *            number of milliseconds to sleep between evictor runs
1899      *
1900      * @see #getDurationBetweenEvictionRuns()
1901      * @deprecated Use {@link #setDurationBetweenEvictionRuns(Duration)}.
1902      */
1903     @Deprecated
1904     public final void setTimeBetweenEvictionRunsMillis(final long timeBetweenEvictionRunsMillis) {
1905         setTimeBetweenEvictionRuns(Duration.ofMillis(timeBetweenEvictionRunsMillis));
1906     }
1907 
1908     /**
1909      * <p>Starts the evictor with the given delay. If there is an evictor
1910      * running when this method is called, it is stopped and replaced with a
1911      * new evictor with the specified delay.</p>
1912      *
1913      * <p>This method needs to be final, since it is called from a constructor.
1914      * See POOL-195.</p>
1915      *
1916      * @param delay time in milliseconds before start and between eviction runs
1917      */
1918     final void startEvictor(final Duration delay) {
1919         synchronized (evictionLock) {
1920             final boolean isPositiverDelay = PoolImplUtils.isPositive(delay);
1921             if (evictor == null) { // Starting evictor for the first time or after a cancel
1922                 if (isPositiverDelay) { // Starting new evictor
1923                     evictor = new Evictor();
1924                     EvictionTimer.schedule(evictor, delay, delay);
1925                 }
1926             } else if (isPositiverDelay) { // Stop or restart of existing evictor: Restart
1927                 synchronized (EvictionTimer.class) { // Ensure no cancel can happen between cancel / schedule calls
1928                     EvictionTimer.cancel(evictor, evictorShutdownTimeoutDuration, true);
1929                     evictor = null;
1930                     evictionIterator = null;
1931                     evictor = new Evictor();
1932                     EvictionTimer.schedule(evictor, delay, delay);
1933                 }
1934             } else { // Stopping evictor
1935                 EvictionTimer.cancel(evictor, evictorShutdownTimeoutDuration, false);
1936             }
1937         }
1938     }
1939 
1940     /**
1941      * Stops the evictor.
1942      */
1943     void stopEvictor() {
1944         startEvictor(Duration.ofMillis(-1L));
1945     }
1946 
1947     /**
1948      * Swallows an exception and notifies the configured listener for swallowed
1949      * exceptions queue.
1950      *
1951      * @param swallowException exception to be swallowed
1952      */
1953     final void swallowException(final Exception swallowException) {
1954         final SwallowedExceptionListener listener = getSwallowedExceptionListener();
1955 
1956         if (listener == null) {
1957             return;
1958         }
1959 
1960         try {
1961             listener.onSwallowException(swallowException);
1962         } catch (final VirtualMachineError e) {
1963             throw e;
1964         } catch (final Throwable ignored) {
1965             // Ignore. Enjoy the irony.
1966         }
1967     }
1968 
1969     @Override
1970     protected void toStringAppendFields(final StringBuilder builder) {
1971         builder.append("maxTotal=");
1972         builder.append(maxTotal);
1973         builder.append(", blockWhenExhausted=");
1974         builder.append(blockWhenExhausted);
1975         builder.append(", maxWaitDuration=");
1976         builder.append(maxWaitDuration);
1977         builder.append(", lifo=");
1978         builder.append(lifo);
1979         builder.append(", fairness=");
1980         builder.append(fairness);
1981         builder.append(", testOnCreate=");
1982         builder.append(testOnCreate);
1983         builder.append(", testOnBorrow=");
1984         builder.append(testOnBorrow);
1985         builder.append(", testOnReturn=");
1986         builder.append(testOnReturn);
1987         builder.append(", testWhileIdle=");
1988         builder.append(testWhileIdle);
1989         builder.append(", durationBetweenEvictionRuns=");
1990         builder.append(durationBetweenEvictionRuns);
1991         builder.append(", numTestsPerEvictionRun=");
1992         builder.append(numTestsPerEvictionRun);
1993         builder.append(", minEvictableIdleTimeDuration=");
1994         builder.append(minEvictableIdleDuration);
1995         builder.append(", softMinEvictableIdleTimeDuration=");
1996         builder.append(softMinEvictableIdleDuration);
1997         builder.append(", evictionPolicy=");
1998         builder.append(evictionPolicy);
1999         builder.append(", closeLock=");
2000         builder.append(closeLock);
2001         builder.append(", closed=");
2002         builder.append(closed);
2003         builder.append(", evictionLock=");
2004         builder.append(evictionLock);
2005         builder.append(", evictor=");
2006         builder.append(evictor);
2007         builder.append(", evictionIterator=");
2008         builder.append(evictionIterator);
2009         builder.append(", factoryClassLoader=");
2010         builder.append(factoryClassLoader);
2011         builder.append(", oname=");
2012         builder.append(objectName);
2013         builder.append(", creationStackTrace=");
2014         builder.append(creationStackTrace);
2015         builder.append(", borrowedCount=");
2016         builder.append(borrowedCount);
2017         builder.append(", returnedCount=");
2018         builder.append(returnedCount);
2019         builder.append(", createdCount=");
2020         builder.append(createdCount);
2021         builder.append(", destroyedCount=");
2022         builder.append(destroyedCount);
2023         builder.append(", destroyedByEvictorCount=");
2024         builder.append(destroyedByEvictorCount);
2025         builder.append(", destroyedByBorrowValidationCount=");
2026         builder.append(destroyedByBorrowValidationCount);
2027         builder.append(", activeTimes=");
2028         builder.append(activeTimes);
2029         builder.append(", idleTimes=");
2030         builder.append(idleTimes);
2031         builder.append(", waitTimes=");
2032         builder.append(waitTimes);
2033         builder.append(", maxBorrowWaitDuration=");
2034         builder.append(maxBorrowWaitDuration);
2035         builder.append(", swallowedExceptionListener=");
2036         builder.append(swallowedExceptionListener);
2037     }
2038 
2039     /**
2040      * Updates statistics after an object is borrowed from the pool.
2041      *
2042      * @param p object borrowed from the pool
2043      * @param waitDuration that the borrowing thread had to wait
2044      */
2045     final void updateStatsBorrow(final PooledObject<T> p, final Duration waitDuration) {
2046         borrowedCount.incrementAndGet();
2047         idleTimes.add(p.getIdleDuration());
2048         waitTimes.add(waitDuration);
2049 
2050         // lock-free optimistic-locking maximum
2051         Duration currentMaxDuration;
2052         do {
2053             currentMaxDuration = maxBorrowWaitDuration.get();
2054             if (currentMaxDuration.compareTo(waitDuration) >= 0) {
2055                 break;
2056             }
2057         } while (!maxBorrowWaitDuration.compareAndSet(currentMaxDuration, waitDuration));
2058     }
2059 
2060     /**
2061      * Updates statistics after an object is returned to the pool.
2062      *
2063      * @param activeTime the amount of time (in milliseconds) that the returning
2064      * object was checked out
2065      */
2066     final void updateStatsReturn(final Duration activeTime) {
2067         returnedCount.incrementAndGet();
2068         activeTimes.add(activeTime);
2069     }
2070 
2071 }