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