View Javadoc
1   /*
2    * Licensed to the Apache Software Foundation (ASF) under one or more
3    * contributor license agreements.  See the NOTICE file distributed with
4    * this work for additional information regarding copyright ownership.
5    * The ASF licenses this file to You under the Apache License, Version 2.0
6    * (the "License"); you may not use this file except in compliance with
7    * the License.  You may obtain a copy of the License at
8    *
9    *      http://www.apache.org/licenses/LICENSE-2.0
10   *
11   * Unless required by applicable law or agreed to in writing, software
12   * distributed under the License is distributed on an "AS IS" BASIS,
13   * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14   * See the License for the specific language governing permissions and
15   * limitations under the License.
16   */
17  package org.apache.commons.pool2.impl;
18  
19  import java.io.PrintWriter;
20  import java.io.StringWriter;
21  import java.io.Writer;
22  import java.lang.management.ManagementFactory;
23  import java.lang.ref.WeakReference;
24  import java.lang.reflect.InvocationTargetException;
25  import java.time.Duration;
26  import java.util.Arrays;
27  import java.util.Deque;
28  import java.util.Iterator;
29  import java.util.TimerTask;
30  import java.util.concurrent.ScheduledFuture;
31  import java.util.concurrent.atomic.AtomicLong;
32  
33  import javax.management.InstanceAlreadyExistsException;
34  import javax.management.InstanceNotFoundException;
35  import javax.management.MBeanRegistrationException;
36  import javax.management.MBeanServer;
37  import javax.management.MalformedObjectNameException;
38  import javax.management.NotCompliantMBeanException;
39  import javax.management.ObjectName;
40  
41  import org.apache.commons.pool2.BaseObject;
42  import org.apache.commons.pool2.PooledObject;
43  import org.apache.commons.pool2.PooledObjectState;
44  import org.apache.commons.pool2.SwallowedExceptionListener;
45  
46  /**
47   * Base class that provides common functionality for {@link GenericObjectPool}
48   * and {@link GenericKeyedObjectPool}. The primary reason this class exists is
49   * reduce code duplication between the two pool implementations.
50   *
51   * @param <T> Type of element pooled in this pool.
52   *
53   * This class is intended to be thread-safe.
54   *
55   * @since 2.0
56   */
57  public abstract class BaseGenericObjectPool<T> extends BaseObject {
58  
59      /**
60       * The idle object eviction iterator. Holds a reference to the idle objects.
61       */
62      class EvictionIterator implements Iterator<PooledObject<T>> {
63  
64          private final Deque<PooledObject<T>> idleObjects;
65          private final Iterator<PooledObject<T>> idleObjectIterator;
66  
67          /**
68           * Create an EvictionIterator for the provided idle instance deque.
69           * @param idleObjects underlying deque
70           */
71          EvictionIterator(final Deque<PooledObject<T>> idleObjects) {
72              this.idleObjects = idleObjects;
73  
74              if (getLifo()) {
75                  idleObjectIterator = idleObjects.descendingIterator();
76              } else {
77                  idleObjectIterator = idleObjects.iterator();
78              }
79          }
80  
81          /**
82           * Gets the idle object deque referenced by this iterator.
83           * @return the idle object deque
84           */
85          public Deque<PooledObject<T>> getIdleObjects() {
86              return idleObjects;
87          }
88  
89          /** {@inheritDoc} */
90          @Override
91          public boolean hasNext() {
92              return idleObjectIterator.hasNext();
93          }
94  
95          /** {@inheritDoc} */
96          @Override
97          public PooledObject<T> next() {
98              return idleObjectIterator.next();
99          }
100 
101         /** {@inheritDoc} */
102         @Override
103         public void remove() {
104             idleObjectIterator.remove();
105         }
106 
107     }
108 
109     /**
110      * The idle object evictor {@link TimerTask}.
111      *
112      * @see GenericKeyedObjectPool#setTimeBetweenEvictionRunsMillis
113      */
114     class Evictor implements Runnable {
115 
116         private ScheduledFuture<?> scheduledFuture;
117 
118         /**
119          * Cancels the scheduled future.
120          */
121         void cancel() {
122             scheduledFuture.cancel(false);
123         }
124 
125 
126         /**
127          * Run pool maintenance.  Evict objects qualifying for eviction and then
128          * ensure that the minimum number of idle instances are available.
129          * Since the Timer that invokes Evictors is shared for all Pools but
130          * pools may exist in different class loaders, the Evictor ensures that
131          * any actions taken are under the class loader of the factory
132          * associated with the pool.
133          */
134         @Override
135         public void run() {
136             final ClassLoader savedClassLoader =
137                     Thread.currentThread().getContextClassLoader();
138             try {
139                 if (factoryClassLoader != null) {
140                     // Set the class loader for the factory
141                     final ClassLoader cl = factoryClassLoader.get();
142                     if (cl == null) {
143                         // The pool has been dereferenced and the class loader
144                         // GC'd. Cancel this timer so the pool can be GC'd as
145                         // well.
146                         cancel();
147                         return;
148                     }
149                     Thread.currentThread().setContextClassLoader(cl);
150                 }
151 
152                 // Evict from the pool
153                 try {
154                     evict();
155                 } catch(final Exception e) {
156                     swallowException(e);
157                 } catch(final OutOfMemoryError oome) {
158                     // Log problem but give evictor thread a chance to continue
159                     // in case error is recoverable
160                     oome.printStackTrace(System.err);
161                 }
162                 // Re-create idle instances.
163                 try {
164                     ensureMinIdle();
165                 } catch (final Exception e) {
166                     swallowException(e);
167                 }
168             } finally {
169                 // Restore the previous CCL
170                 Thread.currentThread().setContextClassLoader(savedClassLoader);
171             }
172         }
173 
174 
175         /**
176          * Sets the scheduled future.
177          *
178          * @param scheduledFuture the scheduled future.
179          */
180         void setScheduledFuture(final ScheduledFuture<?> scheduledFuture) {
181             this.scheduledFuture = scheduledFuture;
182         }
183 
184     }
185 
186     /**
187      * Wrapper for objects under management by the pool.
188      *
189      * GenericObjectPool and GenericKeyedObjectPool maintain references to all
190      * objects under management using maps keyed on the objects. This wrapper
191      * class ensures that objects can work as hash keys.
192      *
193      * @param <T> type of objects in the pool
194      */
195     static class IdentityWrapper<T> {
196         /** Wrapped object */
197         private final T instance;
198 
199         /**
200          * Create a wrapper for an instance.
201          *
202          * @param instance object to wrap
203          */
204         public IdentityWrapper(final T instance) {
205             this.instance = instance;
206         }
207 
208         @Override
209         @SuppressWarnings("rawtypes")
210         public boolean equals(final Object other) {
211             return  other instanceof IdentityWrapper &&
212                     ((IdentityWrapper) other).instance == instance;
213         }
214 
215         /**
216          * @return the wrapped object
217          */
218         public T getObject() {
219             return instance;
220         }
221 
222         @Override
223         public int hashCode() {
224             return System.identityHashCode(instance);
225         }
226 
227         @Override
228         public String toString() {
229             final StringBuilder builder = new StringBuilder();
230             builder.append("IdentityWrapper [instance=");
231             builder.append(instance);
232             builder.append("]");
233             return builder.toString();
234         }
235     }
236     /**
237      * Maintains a cache of values for a single metric and reports
238      * statistics on the cached values.
239      */
240     private class StatsStore {
241 
242         private final AtomicLong[] values;
243         private final int size;
244         private int index;
245 
246         /**
247          * Create a StatsStore with the given cache size.
248          *
249          * @param size number of values to maintain in the cache.
250          */
251         StatsStore(final int size) {
252             this.size = size;
253             values = new AtomicLong[size];
254             for (int i = 0; i < size; i++) {
255                 values[i] = new AtomicLong(-1);
256             }
257         }
258 
259         void add(final Duration value) {
260             add(value.toMillis());
261         }
262 
263         /**
264          * Adds a value to the cache.  If the cache is full, one of the
265          * existing values is replaced by the new value.
266          *
267          * @param value new value to add to the cache.
268          */
269         synchronized void add(final long value) {
270             values[index].set(value);
271             index++;
272             if (index == size) {
273                 index = 0;
274             }
275         }
276 
277         /**
278          * Gets the mean of the cached values.
279          *
280          * @return the mean of the cache, truncated to long
281          */
282         public long getMean() {
283             double result = 0;
284             int counter = 0;
285             for (int i = 0; i < size; i++) {
286                 final long value = values[i].get();
287                 if (value != -1) {
288                     counter++;
289                     result = result * ((counter - 1) / (double) counter) +
290                             value/(double) counter;
291                 }
292             }
293             return (long) result;
294         }
295 
296         @Override
297         public String toString() {
298             final StringBuilder builder = new StringBuilder();
299             builder.append("StatsStore [values=");
300             builder.append(Arrays.toString(values));
301             builder.append(", size=");
302             builder.append(size);
303             builder.append(", index=");
304             builder.append(index);
305             builder.append("]");
306             return builder.toString();
307         }
308     }
309     // Constants
310     /**
311      * The size of the caches used to store historical data for some attributes
312      * so that rolling means may be calculated.
313      */
314     public static final int MEAN_TIMING_STATS_CACHE_SIZE = 100;
315     private static final String EVICTION_POLICY_TYPE_NAME = EvictionPolicy.class.getName();
316     // Configuration attributes
317     private volatile int maxTotal = GenericKeyedObjectPoolConfig.DEFAULT_MAX_TOTAL;
318     private volatile boolean blockWhenExhausted = BaseObjectPoolConfig.DEFAULT_BLOCK_WHEN_EXHAUSTED;
319     private volatile Duration maxWait = BaseObjectPoolConfig.DEFAULT_MAX_WAIT;
320     private volatile boolean lifo = BaseObjectPoolConfig.DEFAULT_LIFO;
321     private final boolean fairness;
322     private volatile boolean testOnCreate = BaseObjectPoolConfig.DEFAULT_TEST_ON_CREATE;
323     private volatile boolean testOnBorrow = BaseObjectPoolConfig.DEFAULT_TEST_ON_BORROW;
324     private volatile boolean testOnReturn = BaseObjectPoolConfig.DEFAULT_TEST_ON_RETURN;
325     private volatile boolean testWhileIdle = BaseObjectPoolConfig.DEFAULT_TEST_WHILE_IDLE;
326     private volatile Duration timeBetweenEvictionRuns = BaseObjectPoolConfig.DEFAULT_TIME_BETWEEN_EVICTION_RUNS;
327     private volatile int numTestsPerEvictionRun = BaseObjectPoolConfig.DEFAULT_NUM_TESTS_PER_EVICTION_RUN;
328 
329     private volatile Duration minEvictableIdleTime = BaseObjectPoolConfig.DEFAULT_MIN_EVICTABLE_IDLE_TIME;
330     private volatile Duration softMinEvictableIdleTime = BaseObjectPoolConfig.DEFAULT_SOFT_MIN_EVICTABLE_IDLE_TIME;
331     private volatile EvictionPolicy<T> evictionPolicy;
332     private volatile Duration evictorShutdownTimeout = BaseObjectPoolConfig.DEFAULT_EVICTOR_SHUTDOWN_TIMEOUT;
333     // Internal (primarily state) attributes
334     final Object closeLock = new Object();
335     volatile boolean closed;
336 
337 
338     final Object evictionLock = new Object();
339     private Evictor evictor = null; // @GuardedBy("evictionLock")
340     EvictionIterator evictionIterator = null; // @GuardedBy("evictionLock")
341     /*
342      * Class loader for evictor thread to use since, in a JavaEE or similar
343      * environment, the context class loader for the evictor thread may not have
344      * visibility of the correct factory. See POOL-161. Uses a weak reference to
345      * avoid potential memory leaks if the Pool is discarded rather than closed.
346      */
347     private final WeakReference<ClassLoader> factoryClassLoader;
348     // Monitoring (primarily JMX) attributes
349     private final ObjectName objectName;
350     private final String creationStackTrace;
351     private final AtomicLong borrowedCount = new AtomicLong(0);
352     private final AtomicLong returnedCount = new AtomicLong(0);
353     final AtomicLong createdCount = new AtomicLong(0);
354     final AtomicLong destroyedCount = new AtomicLong(0);
355     final AtomicLong destroyedByEvictorCount = new AtomicLong(0);
356     final AtomicLong destroyedByBorrowValidationCount = new AtomicLong(0);
357     private final StatsStore activeTimes = new StatsStore(MEAN_TIMING_STATS_CACHE_SIZE);
358 
359 
360     private final StatsStore idleTimes = new StatsStore(MEAN_TIMING_STATS_CACHE_SIZE);
361 
362 
363     private final StatsStore waitTimes = new StatsStore(MEAN_TIMING_STATS_CACHE_SIZE);
364 
365     private final AtomicLong maxBorrowWaitTimeMillis = new AtomicLong(0L);
366 
367     private volatile SwallowedExceptionListener swallowedExceptionListener = null;
368 
369     /**
370      * Handles JMX registration (if required) and the initialization required for
371      * monitoring.
372      *
373      * @param config        Pool configuration
374      * @param jmxNameBase   The default base JMX name for the new pool unless
375      *                      overridden by the config
376      * @param jmxNamePrefix Prefix to be used for JMX name for the new pool
377      */
378     public BaseGenericObjectPool(final BaseObjectPoolConfig<T> config,
379             final String jmxNameBase, final String jmxNamePrefix) {
380         if (config.getJmxEnabled()) {
381             this.objectName = jmxRegister(config, jmxNameBase, jmxNamePrefix);
382         } else {
383             this.objectName = null;
384         }
385 
386         // Populate the creation stack trace
387         this.creationStackTrace = getStackTrace(new Exception());
388 
389         // save the current TCCL (if any) to be used later by the evictor Thread
390         final ClassLoader cl = Thread.currentThread().getContextClassLoader();
391         if (cl == null) {
392             factoryClassLoader = null;
393         } else {
394             factoryClassLoader = new WeakReference<>(cl);
395         }
396 
397         fairness = config.getFairness();
398     }
399 
400     /**
401      * Verifies that the pool is open.
402      * @throws IllegalStateException if the pool is closed.
403      */
404     final void assertOpen() throws IllegalStateException {
405         if (isClosed()) {
406             throw new IllegalStateException("Pool not open");
407         }
408     }
409 
410     /**
411      * Closes the pool, destroys the remaining idle objects and, if registered
412      * in JMX, deregisters it.
413      */
414     public abstract void close();
415 
416     /**
417      * Tries to ensure that the configured minimum number of idle instances are
418      * available in the pool.
419      * @throws Exception if an error occurs creating idle instances
420      */
421     abstract void ensureMinIdle() throws Exception;
422 
423     /**
424      * <p>Perform {@code numTests} idle object eviction tests, evicting
425      * examined objects that meet the criteria for eviction. If
426      * {@code testWhileIdle} is true, examined objects are validated
427      * when visited (and removed if invalid); otherwise only objects that
428      * have been idle for more than {@code minEvicableIdleTimeMillis}
429      * are removed.</p>
430      *
431      * @throws Exception when there is a problem evicting idle objects.
432      */
433     public abstract void evict() throws Exception;
434 
435     /**
436      * Gets whether to block when the {@code borrowObject()} method is
437      * invoked when the pool is exhausted (the maximum number of "active"
438      * objects has been reached).
439      *
440      * @return {@code true} if {@code borrowObject()} should block
441      *         when the pool is exhausted
442      *
443      * @see #setBlockWhenExhausted
444      */
445     public final boolean getBlockWhenExhausted() {
446         return blockWhenExhausted;
447     }
448 
449     /**
450      * The total number of objects successfully borrowed from this pool over the
451      * lifetime of the pool.
452      * @return the borrowed object count
453      */
454     public final long getBorrowedCount() {
455         return borrowedCount.get();
456     }
457 
458     /**
459      * The total number of objects created for this pool over the lifetime of
460      * the pool.
461      * @return the created object count
462      */
463     public final long getCreatedCount() {
464         return createdCount.get();
465     }
466 
467     /**
468      * Provides the stack trace for the call that created this pool. JMX
469      * registration may trigger a memory leak so it is important that pools are
470      * deregistered when no longer used by calling the {@link #close()} method.
471      * This method is provided to assist with identifying code that creates but
472      * does not close it thereby creating a memory leak.
473      * @return pool creation stack trace
474      */
475     public final String getCreationStackTrace() {
476         return creationStackTrace;
477     }
478 
479     /**
480      * The total number of objects destroyed by this pool as a result of failing
481      * validation during {@code borrowObject()} over the lifetime of the
482      * pool.
483      * @return validation destroyed object count
484      */
485     public final long getDestroyedByBorrowValidationCount() {
486         return destroyedByBorrowValidationCount.get();
487     }
488 
489     /**
490      * The total number of objects destroyed by the evictor associated with this
491      * pool over the lifetime of the pool.
492      * @return the evictor destroyed object count
493      */
494     public final long getDestroyedByEvictorCount() {
495         return destroyedByEvictorCount.get();
496     }
497 
498     /**
499      * The total number of objects destroyed by this pool over the lifetime of
500      * the pool.
501      * @return the destroyed object count
502      */
503     public final long getDestroyedCount() {
504         return destroyedCount.get();
505     }
506 
507     /**
508      * Gets the {@link EvictionPolicy} defined for this pool.
509      *
510      * @return the eviction policy
511      * @since 2.4
512      * @since 2.6.0 Changed access from protected to public.
513      */
514     public EvictionPolicy<T> getEvictionPolicy() {
515         return evictionPolicy;
516     }
517 
518     /**
519      * Gets the name of the {@link EvictionPolicy} implementation that is
520      * used by this pool.
521      *
522      * @return  The fully qualified class name of the {@link EvictionPolicy}
523      *
524      * @see #setEvictionPolicyClassName(String)
525      */
526     public final String getEvictionPolicyClassName() {
527         return evictionPolicy.getClass().getName();
528     }
529 
530     /**
531      * Gets the timeout that will be used when waiting for the Evictor to
532      * shutdown if this pool is closed and it is the only pool still using the
533      * the value for the Evictor.
534      *
535      * @return  The timeout that will be used while waiting for
536      *          the Evictor to shut down.
537      * @since 2.10.0
538      */
539     public final Duration getEvictorShutdownTimeout() {
540         return evictorShutdownTimeout;
541     }
542 
543     /**
544      * Gets the timeout that will be used when waiting for the Evictor to
545      * shutdown if this pool is closed and it is the only pool still using the
546      * the value for the Evictor.
547      *
548      * @return  The timeout in milliseconds that will be used while waiting for
549      *          the Evictor to shut down.
550      * @deprecated Use {@link #getEvictorShutdownTimeout()}.
551      */
552     @Deprecated
553     public final long getEvictorShutdownTimeoutMillis() {
554         return evictorShutdownTimeout.toMillis();
555     }
556 
557     /**
558      * Gets whether or not the pool serves threads waiting to borrow objects fairly.
559      * True means that waiting threads are served as if waiting in a FIFO queue.
560      *
561      * @return {@code true} if waiting threads are to be served
562      *             by the pool in arrival order
563      */
564     public final boolean getFairness() {
565         return fairness;
566     }
567 
568     /**
569      * Provides the name under which the pool has been registered with the
570      * platform MBean server or {@code null} if the pool has not been
571      * registered.
572      * @return the JMX name
573      */
574     public final ObjectName getJmxName() {
575         return objectName;
576     }
577 
578     /**
579      * Gets whether the pool has LIFO (last in, first out) behavior with
580      * respect to idle objects - always returning the most recently used object
581      * from the pool, or as a FIFO (first in, first out) queue, where the pool
582      * always returns the oldest object in the idle object pool.
583      *
584      * @return {@code true} if the pool is configured with LIFO behavior
585      *         or {@code false} if the pool is configured with FIFO
586      *         behavior
587      *
588      * @see #setLifo
589      */
590     public final boolean getLifo() {
591         return lifo;
592     }
593 
594     /**
595      * The maximum time a thread has waited to borrow objects from the pool.
596      * @return maximum wait time in milliseconds since the pool was created
597      */
598     public final long getMaxBorrowWaitTimeMillis() {
599         return maxBorrowWaitTimeMillis.get();
600     }
601 
602     /**
603      * Gets the maximum number of objects that can be allocated by the pool
604      * (checked out to clients, or idle awaiting checkout) at a given time. When
605      * negative, there is no limit to the number of objects that can be
606      * managed by the pool at one time.
607      *
608      * @return the cap on the total number of object instances managed by the
609      *         pool.
610      *
611      * @see #setMaxTotal
612      */
613     public final int getMaxTotal() {
614         return maxTotal;
615     }
616 
617     /**
618      * Gets the maximum amount of time (in milliseconds) the
619      * {@code borrowObject()} method should block before throwing an
620      * exception when the pool is exhausted and
621      * {@link #getBlockWhenExhausted} is true. When less than 0, the
622      * {@code borrowObject()} method may block indefinitely.
623      *
624      * @return the maximum number of milliseconds {@code borrowObject()}
625      *         will block.
626      *
627      * @see #setMaxWaitMillis
628      * @see #setBlockWhenExhausted
629      */
630     public final long getMaxWaitMillis() {
631         return maxWait.toMillis();
632     }
633 
634     /**
635      * The mean time objects are active for based on the last {@link
636      * #MEAN_TIMING_STATS_CACHE_SIZE} objects returned to the pool.
637      * @return mean time an object has been checked out from the pool among
638      * recently returned objects
639      */
640     public final long getMeanActiveTimeMillis() {
641         return activeTimes.getMean();
642     }
643 
644     /**
645      * The mean time threads wait to borrow an object based on the last {@link
646      * #MEAN_TIMING_STATS_CACHE_SIZE} objects borrowed from the pool.
647      * @return mean time in milliseconds that a recently served thread has had
648      * to wait to borrow an object from the pool
649      */
650     public final long getMeanBorrowWaitTimeMillis() {
651         return waitTimes.getMean();
652     }
653 
654     /**
655      * The mean time objects are idle for based on the last {@link
656      * #MEAN_TIMING_STATS_CACHE_SIZE} objects borrowed from the pool.
657      * @return mean time an object has been idle in the pool among recently
658      * borrowed objects
659      */
660     public final long getMeanIdleTimeMillis() {
661         return idleTimes.getMean();
662     }
663 
664     /**
665      * Gets the minimum amount of time an object may sit idle in the pool
666      * before it is eligible for eviction by the idle object evictor (if any -
667      * see {@link #setTimeBetweenEvictionRuns(Duration)}). When non-positive,
668      * no objects will be evicted from the pool due to idle time alone.
669      *
670      * @return minimum amount of time an object may sit idle in the pool before
671      *         it is eligible for eviction
672      *
673      * @see #setMinEvictableIdleTimeMillis
674      * @see #setTimeBetweenEvictionRunsMillis
675      * @since 2.10.0
676      */
677     public final Duration getMinEvictableIdleTime() {
678         return minEvictableIdleTime;
679     }
680 
681     /**
682      * Gets the minimum amount of time an object may sit idle in the pool
683      * before it is eligible for eviction by the idle object evictor (if any -
684      * see {@link #setTimeBetweenEvictionRunsMillis(long)}). When non-positive,
685      * no objects will be evicted from the pool due to idle time alone.
686      *
687      * @return minimum amount of time an object may sit idle in the pool before
688      *         it is eligible for eviction
689      *
690      * @see #setMinEvictableIdleTimeMillis
691      * @see #setTimeBetweenEvictionRunsMillis
692      * @deprecated Use {@link #getMinEvictableIdleTime()}.
693      */
694     @Deprecated
695     public final long getMinEvictableIdleTimeMillis() {
696         return minEvictableIdleTime.toMillis();
697     }
698 
699     /**
700      * The number of instances currently idle in this pool.
701      * @return count of instances available for checkout from the pool
702      */
703     public abstract int getNumIdle();
704 
705     /**
706      * Gets the maximum number of objects to examine during each run (if any)
707      * of the idle object evictor thread. When positive, the number of tests
708      * performed for a run will be the minimum of the configured value and the
709      * number of idle instances in the pool. When negative, the number of tests
710      * performed will be <code>ceil({@link #getNumIdle}/
711      * abs({@link #getNumTestsPerEvictionRun}))</code> which means that when the
712      * value is {@code -n} roughly one nth of the idle objects will be
713      * tested per run.
714      *
715      * @return max number of objects to examine during each evictor run
716      *
717      * @see #setNumTestsPerEvictionRun
718      * @see #setTimeBetweenEvictionRunsMillis
719      */
720     public final int getNumTestsPerEvictionRun() {
721         return numTestsPerEvictionRun;
722     }
723 
724     /**
725      * The total number of objects returned to this pool over the lifetime of
726      * the pool. This excludes attempts to return the same object multiple
727      * times.
728      * @return the returned object count
729      */
730     public final long getReturnedCount() {
731         return returnedCount.get();
732     }
733 
734     /**
735      * Gets the minimum amount of time an object may sit idle in the pool
736      * before it is eligible for eviction by the idle object evictor (if any -
737      * see {@link #setTimeBetweenEvictionRuns(Duration)}),
738      * with the extra condition that at least {@code minIdle} object
739      * instances remain in the pool. This setting is overridden by
740      * {@link #getMinEvictableIdleTime} (that is, if
741      * {@link #getMinEvictableIdleTime} is positive, then
742      * {@link #getSoftMinEvictableIdleTime} is ignored).
743      *
744      * @return minimum amount of time an object may sit idle in the pool before
745      *         it is eligible for eviction if minIdle instances are available
746      *
747      * @see #setSoftMinEvictableIdleTime(Duration)
748      * @since 2.10.0
749      */
750     public final Duration getSoftMinEvictableIdleTime() {
751         return softMinEvictableIdleTime;
752     }
753 
754     /**
755      * Gets the minimum amount of time an object may sit idle in the pool
756      * before it is eligible for eviction by the idle object evictor (if any -
757      * see {@link #setTimeBetweenEvictionRunsMillis(long)}),
758      * with the extra condition that at least {@code minIdle} object
759      * instances remain in the pool. This setting is overridden by
760      * {@link #getMinEvictableIdleTimeMillis} (that is, if
761      * {@link #getMinEvictableIdleTimeMillis} is positive, then
762      * {@link #getSoftMinEvictableIdleTimeMillis} is ignored).
763      *
764      * @return minimum amount of time an object may sit idle in the pool before
765      *         it is eligible for eviction if minIdle instances are available
766      *
767      * @see #setSoftMinEvictableIdleTimeMillis
768      * @deprecated Use {@link #getSoftMinEvictableIdleTime()}.
769      */
770     @Deprecated
771     public final long getSoftMinEvictableIdleTimeMillis() {
772         return softMinEvictableIdleTime.toMillis();
773     }
774 
775     /**
776      * Gets the stack trace of an exception as a string.
777      * @param e exception to trace
778      * @return exception stack trace as a string
779      */
780     private String getStackTrace(final Exception e) {
781         // Need the exception in string form to prevent the retention of
782         // references to classes in the stack trace that could trigger a memory
783         // leak in a container environment.
784         final Writer w = new StringWriter();
785         final PrintWriter pw = new PrintWriter(w);
786         e.printStackTrace(pw);
787         return w.toString();
788     }
789 
790     /**
791      * The listener used (if any) to receive notifications of exceptions
792      * unavoidably swallowed by the pool.
793      *
794      * @return The listener or {@code null} for no listener
795      */
796     public final SwallowedExceptionListener getSwallowedExceptionListener() {
797         return swallowedExceptionListener;
798     }
799 
800     /**
801      * Gets whether objects borrowed from the pool will be validated before
802      * being returned from the {@code borrowObject()} method. Validation is
803      * performed by the {@code validateObject()} method of the factory
804      * associated with the pool. If the object fails to validate, it will be
805      * removed from the pool and destroyed, and a new attempt will be made to
806      * borrow an object from the pool.
807      *
808      * @return {@code true} if objects are validated before being returned
809      *         from the {@code borrowObject()} method
810      *
811      * @see #setTestOnBorrow
812      */
813     public final boolean getTestOnBorrow() {
814         return testOnBorrow;
815     }
816 
817     /**
818      * Gets whether objects created for the pool will be validated before
819      * being returned from the {@code borrowObject()} method. Validation is
820      * performed by the {@code validateObject()} method of the factory
821      * associated with the pool. If the object fails to validate, then
822      * {@code borrowObject()} will fail.
823      *
824      * @return {@code true} if newly created objects are validated before
825      *         being returned from the {@code borrowObject()} method
826      *
827      * @see #setTestOnCreate
828      *
829      * @since 2.2
830      */
831     public final boolean getTestOnCreate() {
832         return testOnCreate;
833     }
834 
835     /**
836      * Gets whether objects borrowed from the pool will be validated when
837      * they are returned to the pool via the {@code returnObject()} method.
838      * Validation is performed by the {@code validateObject()} method of
839      * the factory associated with the pool. Returning objects that fail validation
840      * are destroyed rather then being returned the pool.
841      *
842      * @return {@code true} if objects are validated on return to
843      *         the pool via the {@code returnObject()} method
844      *
845      * @see #setTestOnReturn
846      */
847     public final boolean getTestOnReturn() {
848         return testOnReturn;
849     }
850 
851     /**
852      * Gets whether objects sitting idle in the pool will be validated by the
853      * idle object evictor (if any - see
854      * {@link #setTimeBetweenEvictionRuns(Duration)}). Validation is performed
855      * by the {@code validateObject()} method of the factory associated
856      * with the pool. If the object fails to validate, it will be removed from
857      * the pool and destroyed.
858      *
859      * @return {@code true} if objects will be validated by the evictor
860      *
861      * @see #setTestWhileIdle
862      * @see #setTimeBetweenEvictionRunsMillis
863      */
864     public final boolean getTestWhileIdle() {
865         return testWhileIdle;
866     }
867 
868     /**
869      * Gets the duration to sleep between runs of the idle
870      * object evictor thread. When non-positive, no idle object evictor thread
871      * will be run.
872      *
873      * @return number of milliseconds to sleep between evictor runs
874      *
875      * @see #setTimeBetweenEvictionRuns
876      * @since 2.10.0
877      */
878     public final Duration getTimeBetweenEvictionRuns() {
879         return timeBetweenEvictionRuns;
880     }
881 
882     /**
883      * Gets the number of milliseconds to sleep between runs of the idle
884      * object evictor thread. When non-positive, no idle object evictor thread
885      * will be run.
886      *
887      * @return number of milliseconds to sleep between evictor runs
888      *
889      * @see #setTimeBetweenEvictionRunsMillis
890      * @deprecated Use {@link #getTimeBetweenEvictionRuns()}.
891      */
892     @Deprecated
893     public final long getTimeBetweenEvictionRunsMillis() {
894         return timeBetweenEvictionRuns.toMillis();
895     }
896 
897     /**
898      * Has this pool instance been closed.
899      * @return {@code true} when this pool has been closed.
900      */
901     public final boolean isClosed() {
902         return closed;
903     }
904 
905     /**
906      * Registers the pool with the platform MBean server.
907      * The registered name will be
908      * {@code jmxNameBase + jmxNamePrefix + i} where i is the least
909      * integer greater than or equal to 1 such that the name is not already
910      * registered. Swallows MBeanRegistrationException, NotCompliantMBeanException
911      * returning null.
912      *
913      * @param config Pool configuration
914      * @param jmxNameBase default base JMX name for this pool
915      * @param jmxNamePrefix name prefix
916      * @return registered ObjectName, null if registration fails
917      */
918     private ObjectName jmxRegister(final BaseObjectPoolConfig<T> config,
919             final String jmxNameBase, String jmxNamePrefix) {
920         ObjectName newObjectName = null;
921         final MBeanServer mbs = ManagementFactory.getPlatformMBeanServer();
922         int i = 1;
923         boolean registered = false;
924         String base = config.getJmxNameBase();
925         if (base == null) {
926             base = jmxNameBase;
927         }
928         while (!registered) {
929             try {
930                 ObjectName objName;
931                 // Skip the numeric suffix for the first pool in case there is
932                 // only one so the names are cleaner.
933                 if (i == 1) {
934                     objName = new ObjectName(base + jmxNamePrefix);
935                 } else {
936                     objName = new ObjectName(base + jmxNamePrefix + i);
937                 }
938                 mbs.registerMBean(this, objName);
939                 newObjectName = objName;
940                 registered = true;
941             } catch (final MalformedObjectNameException e) {
942                 if (BaseObjectPoolConfig.DEFAULT_JMX_NAME_PREFIX.equals(
943                         jmxNamePrefix) && jmxNameBase.equals(base)) {
944                     // Shouldn't happen. Skip registration if it does.
945                     registered = true;
946                 } else {
947                     // Must be an invalid name. Use the defaults instead.
948                     jmxNamePrefix =
949                             BaseObjectPoolConfig.DEFAULT_JMX_NAME_PREFIX;
950                     base = jmxNameBase;
951                 }
952             } catch (final InstanceAlreadyExistsException e) {
953                 // Increment the index and try again
954                 i++;
955             } catch (final MBeanRegistrationException | NotCompliantMBeanException e) {
956                 // Shouldn't happen. Skip registration if it does.
957                 registered = true;
958             }
959         }
960         return newObjectName;
961     }
962 
963     /**
964      * Unregisters this pool's MBean.
965      */
966     final void jmxUnregister() {
967         if (objectName != null) {
968             try {
969                 ManagementFactory.getPlatformMBeanServer().unregisterMBean(
970                         objectName);
971             } catch (final MBeanRegistrationException | InstanceNotFoundException e) {
972                 swallowException(e);
973             }
974         }
975     }
976 
977     /**
978      * Marks the object as returning to the pool.
979      * @param pooledObject instance to return to the keyed pool
980      */
981     protected void markReturningState(final PooledObject<T> pooledObject) {
982         synchronized(pooledObject) {
983             final PooledObjectState state = pooledObject.getState();
984             if (state != PooledObjectState.ALLOCATED) {
985                 throw new IllegalStateException(
986                         "Object has already been returned to this pool or is invalid");
987             }
988             pooledObject.markReturning(); // Keep from being marked abandoned
989         }
990     }
991 
992     /**
993      * Sets whether to block when the {@code borrowObject()} method is
994      * invoked when the pool is exhausted (the maximum number of "active"
995      * objects has been reached).
996      *
997      * @param blockWhenExhausted    {@code true} if
998      *                              {@code borrowObject()} should block
999      *                              when the pool is exhausted
1000      *
1001      * @see #getBlockWhenExhausted
1002      */
1003     public final void setBlockWhenExhausted(final boolean blockWhenExhausted) {
1004         this.blockWhenExhausted = blockWhenExhausted;
1005     }
1006     /**
1007      * Initializes the receiver with the given configuration.
1008      *
1009      * @param config Initialization source.
1010      */
1011     protected void setConfig(final BaseObjectPoolConfig<T> config) {
1012         setLifo(config.getLifo());
1013         setMaxWaitMillis(config.getMaxWaitMillis());
1014         setBlockWhenExhausted(config.getBlockWhenExhausted());
1015         setTestOnCreate(config.getTestOnCreate());
1016         setTestOnBorrow(config.getTestOnBorrow());
1017         setTestOnReturn(config.getTestOnReturn());
1018         setTestWhileIdle(config.getTestWhileIdle());
1019         setNumTestsPerEvictionRun(config.getNumTestsPerEvictionRun());
1020         setMinEvictableIdleTime(config.getMinEvictableIdleTime());
1021         setTimeBetweenEvictionRuns(config.getTimeBetweenEvictionRuns());
1022         setSoftMinEvictableIdleTime(config.getSoftMinEvictableIdleTime());
1023         final EvictionPolicy<T> policy = config.getEvictionPolicy();
1024         if (policy == null) {
1025             // Use the class name (pre-2.6.0 compatible)
1026             setEvictionPolicyClassName(config.getEvictionPolicyClassName());
1027         } else {
1028             // Otherwise, use the class (2.6.0 feature)
1029             setEvictionPolicy(policy);
1030         }
1031         setEvictorShutdownTimeout(config.getEvictorShutdownTimeout());
1032     }
1033 
1034 
1035     // Monitoring (primarily JMX) related methods
1036 
1037     /**
1038      * Sets the eviction policy for this pool.
1039      *
1040      * @param evictionPolicy
1041      *            the eviction policy for this pool.
1042      * @since 2.6.0
1043      */
1044     public void setEvictionPolicy(final EvictionPolicy<T> evictionPolicy) {
1045         this.evictionPolicy = evictionPolicy;
1046     }
1047 
1048     /**
1049      * Sets the eviction policy.
1050      *
1051      * @param className Eviction policy class name.
1052      * @param classLoader Load the class from this class loader.
1053      */
1054     @SuppressWarnings("unchecked")
1055     private void setEvictionPolicy(final String className, final ClassLoader classLoader)
1056             throws ClassNotFoundException, InstantiationException, IllegalAccessException, InvocationTargetException, NoSuchMethodException {
1057         final Class<?> clazz = Class.forName(className, true, classLoader);
1058         final Object policy = clazz.getConstructor().newInstance();
1059         this.evictionPolicy = (EvictionPolicy<T>) policy;
1060     }
1061 
1062     /**
1063      * Sets the name of the {@link EvictionPolicy} implementation that is used by this pool. The Pool will attempt to
1064      * load the class using the thread context class loader. If that fails, the use the class loader for the
1065      * {@link EvictionPolicy} interface.
1066      *
1067      * @param evictionPolicyClassName
1068      *            the fully qualified class name of the new eviction policy
1069      *
1070      * @see #getEvictionPolicyClassName()
1071      * @since 2.6.0 If loading the class using the thread context class loader fails, use the class loader for the
1072      *        {@link EvictionPolicy} interface.
1073      */
1074     public final void setEvictionPolicyClassName(final String evictionPolicyClassName) {
1075         setEvictionPolicyClassName(evictionPolicyClassName, Thread.currentThread().getContextClassLoader());
1076     }
1077 
1078     /**
1079      * Sets the name of the {@link EvictionPolicy} implementation that is used by this pool. The Pool will attempt to
1080      * load the class using the given class loader. If that fails, use the class loader for the {@link EvictionPolicy}
1081      * interface.
1082      *
1083      * @param evictionPolicyClassName
1084      *            the fully qualified class name of the new eviction policy
1085      * @param classLoader
1086      *            the class loader to load the given {@code evictionPolicyClassName}.
1087      *
1088      * @see #getEvictionPolicyClassName()
1089      * @since 2.6.0 If loading the class using the given class loader fails, use the class loader for the
1090      *        {@link EvictionPolicy} interface.
1091      */
1092     public final void setEvictionPolicyClassName(final String evictionPolicyClassName, final ClassLoader classLoader) {
1093         // Getting epClass here and now best matches the caller's environment
1094         final Class<?> epClass = EvictionPolicy.class;
1095         final ClassLoader epClassLoader = epClass.getClassLoader();
1096         try {
1097             try {
1098                 setEvictionPolicy(evictionPolicyClassName, classLoader);
1099             } catch (final ClassCastException | ClassNotFoundException e) {
1100                 setEvictionPolicy(evictionPolicyClassName, epClassLoader);
1101             }
1102         } catch (final ClassCastException e) {
1103             throw new IllegalArgumentException("Class " + evictionPolicyClassName + " from class loaders [" +
1104                     classLoader + ", " + epClassLoader + "] do not implement " + EVICTION_POLICY_TYPE_NAME);
1105         } catch (final ClassNotFoundException | InstantiationException | IllegalAccessException |
1106                 InvocationTargetException | NoSuchMethodException e) {
1107             final String exMessage = "Unable to create " + EVICTION_POLICY_TYPE_NAME + " instance of type " +
1108                     evictionPolicyClassName;
1109             throw new IllegalArgumentException(exMessage, e);
1110         }
1111     }
1112 
1113     /**
1114      * Sets the timeout that will be used when waiting for the Evictor to shutdown if this pool is closed and it is the
1115      * only pool still using the the value for the Evictor.
1116      *
1117      * @param evictorShutdownTimeoutMillis the timeout in milliseconds that will be used while waiting for the Evictor
1118      *                                     to shut down.
1119      * @since 2.10.0
1120      */
1121     public final void setEvictorShutdownTimeout(final Duration evictorShutdownTimeoutMillis) {
1122         this.evictorShutdownTimeout = evictorShutdownTimeoutMillis;
1123     }
1124 
1125     /**
1126      * Sets the timeout that will be used when waiting for the Evictor to shutdown if this pool is closed and it is the
1127      * only pool still using the the value for the Evictor.
1128      *
1129      * @param evictorShutdownTimeoutMillis the timeout in milliseconds that will be used while waiting for the Evictor
1130      *                                     to shut down.
1131      * @deprecated Use {@link #setEvictorShutdownTimeout(Duration)}.
1132      */
1133     @Deprecated
1134     public final void setEvictorShutdownTimeoutMillis(final long evictorShutdownTimeoutMillis) {
1135         this.evictorShutdownTimeout = Duration.ofMillis(evictorShutdownTimeoutMillis);
1136     }
1137 
1138     /**
1139      * Sets whether the pool has LIFO (last in, first out) behavior with
1140      * respect to idle objects - always returning the most recently used object
1141      * from the pool, or as a FIFO (first in, first out) queue, where the pool
1142      * always returns the oldest object in the idle object pool.
1143      *
1144      * @param lifo  {@code true} if the pool is to be configured with LIFO
1145      *              behavior or {@code false} if the pool is to be
1146      *              configured with FIFO behavior
1147      *
1148      * @see #getLifo()
1149      */
1150     public final void setLifo(final boolean lifo) {
1151         this.lifo = lifo;
1152     }
1153 
1154     /**
1155      * Sets the cap on the number of objects that can be allocated by the pool
1156      * (checked out to clients, or idle awaiting checkout) at a given time. Use
1157      * a negative value for no limit.
1158      *
1159      * @param maxTotal  The cap on the total number of object instances managed
1160      *                  by the pool. Negative values mean that there is no limit
1161      *                  to the number of objects allocated by the pool.
1162      *
1163      * @see #getMaxTotal
1164      */
1165     public final void setMaxTotal(final int maxTotal) {
1166         this.maxTotal = maxTotal;
1167     }
1168 
1169     /**
1170      * Sets the maximum amount of time (in milliseconds) the
1171      * {@code borrowObject()} method should block before throwing an
1172      * exception when the pool is exhausted and
1173      * {@link #getBlockWhenExhausted} is true. When less than 0, the
1174      * {@code borrowObject()} method may block indefinitely.
1175      *
1176      * @param maxWaitMillis the maximum number of milliseconds
1177      *                      {@code borrowObject()} will block or negative
1178      *                      for indefinitely.
1179      *
1180      * @see #getMaxWaitMillis
1181      * @see #setBlockWhenExhausted
1182      */
1183     public final void setMaxWaitMillis(final long maxWaitMillis) {
1184         this.maxWait = Duration.ofMillis(maxWaitMillis);
1185     }
1186 
1187     /**
1188      * Sets the minimum amount of time an object may sit idle in the pool
1189      * before it is eligible for eviction by the idle object evictor (if any -
1190      * see {@link #setTimeBetweenEvictionRuns(Duration)}). When non-positive,
1191      * no objects will be evicted from the pool due to idle time alone.
1192      *
1193      * @param minEvictableIdleTimeMillis
1194      *            minimum amount of time an object may sit idle in the pool
1195      *            before it is eligible for eviction
1196      *
1197      * @see #getMinEvictableIdleTime
1198      * @see #setTimeBetweenEvictionRuns
1199      * @since 2.10.0
1200      */
1201     public final void setMinEvictableIdleTime(final Duration minEvictableIdleTimeMillis) {
1202         this.minEvictableIdleTime = minEvictableIdleTimeMillis;
1203     }
1204 
1205     /**
1206      * Sets the minimum amount of time an object may sit idle in the pool
1207      * before it is eligible for eviction by the idle object evictor (if any -
1208      * see {@link #setTimeBetweenEvictionRunsMillis(long)}). When non-positive,
1209      * no objects will be evicted from the pool due to idle time alone.
1210      *
1211      * @param minEvictableIdleTimeMillis
1212      *            minimum amount of time an object may sit idle in the pool
1213      *            before it is eligible for eviction
1214      *
1215      * @see #getMinEvictableIdleTimeMillis
1216      * @see #setTimeBetweenEvictionRunsMillis
1217      * @deprecated Use {@link #setMinEvictableIdleTime(Duration)}.
1218      */
1219     @Deprecated
1220     public final void setMinEvictableIdleTimeMillis(final long minEvictableIdleTimeMillis) {
1221         this.minEvictableIdleTime = Duration.ofMillis(minEvictableIdleTimeMillis);
1222     }
1223 
1224     /**
1225      * Sets the maximum number of objects to examine during each run (if any)
1226      * of the idle object evictor thread. When positive, the number of tests
1227      * performed for a run will be the minimum of the configured value and the
1228      * number of idle instances in the pool. When negative, the number of tests
1229      * performed will be <code>ceil({@link #getNumIdle}/
1230      * abs({@link #getNumTestsPerEvictionRun}))</code> which means that when the
1231      * value is {@code -n} roughly one nth of the idle objects will be
1232      * tested per run.
1233      *
1234      * @param numTestsPerEvictionRun
1235      *            max number of objects to examine during each evictor run
1236      *
1237      * @see #getNumTestsPerEvictionRun
1238      * @see #setTimeBetweenEvictionRunsMillis
1239      */
1240     public final void setNumTestsPerEvictionRun(final int numTestsPerEvictionRun) {
1241         this.numTestsPerEvictionRun = numTestsPerEvictionRun;
1242     }
1243 
1244     /**
1245      * Sets the minimum amount of time an object may sit idle in the pool
1246      * before it is eligible for eviction by the idle object evictor (if any -
1247      * see {@link #setTimeBetweenEvictionRuns(Duration)}),
1248      * with the extra condition that at least {@code minIdle} object
1249      * instances remain in the pool. This setting is overridden by
1250      * {@link #getMinEvictableIdleTime} (that is, if
1251      * {@link #getMinEvictableIdleTime} is positive, then
1252      * {@link #getSoftMinEvictableIdleTime} is ignored).
1253      *
1254      * @param softMinEvictableIdleTime
1255      *            minimum amount of time an object may sit idle in the pool
1256      *            before it is eligible for eviction if minIdle instances are
1257      *            available
1258      *
1259      * @see #getSoftMinEvictableIdleTimeMillis
1260      * @since 2.10.0
1261      */
1262     public final void setSoftMinEvictableIdleTime(final Duration softMinEvictableIdleTime) {
1263         this.softMinEvictableIdleTime = softMinEvictableIdleTime;
1264     }
1265 
1266     /**
1267      * Sets the minimum amount of time an object may sit idle in the pool
1268      * before it is eligible for eviction by the idle object evictor (if any -
1269      * see {@link #setTimeBetweenEvictionRunsMillis(long)}),
1270      * with the extra condition that at least {@code minIdle} object
1271      * instances remain in the pool. This setting is overridden by
1272      * {@link #getMinEvictableIdleTimeMillis} (that is, if
1273      * {@link #getMinEvictableIdleTimeMillis} is positive, then
1274      * {@link #getSoftMinEvictableIdleTimeMillis} is ignored).
1275      *
1276      * @param softMinEvictableIdleTimeMillis
1277      *            minimum amount of time an object may sit idle in the pool
1278      *            before it is eligible for eviction if minIdle instances are
1279      *            available
1280      *
1281      * @see #getSoftMinEvictableIdleTimeMillis
1282      * @deprecated Use {@link #setSoftMinEvictableIdleTime(Duration)}.
1283      */
1284     @Deprecated
1285     public final void setSoftMinEvictableIdleTimeMillis(final long softMinEvictableIdleTimeMillis) {
1286         this.softMinEvictableIdleTime = Duration.ofMillis(softMinEvictableIdleTimeMillis);
1287     }
1288 
1289     /**
1290      * The listener used (if any) to receive notifications of exceptions
1291      * unavoidably swallowed by the pool.
1292      *
1293      * @param swallowedExceptionListener    The listener or {@code null}
1294      *                                      for no listener
1295      */
1296     public final void setSwallowedExceptionListener(
1297             final SwallowedExceptionListener swallowedExceptionListener) {
1298         this.swallowedExceptionListener = swallowedExceptionListener;
1299     }
1300 
1301     /**
1302      * Sets whether objects borrowed from the pool will be validated before
1303      * being returned from the {@code borrowObject()} method. Validation is
1304      * performed by the {@code validateObject()} method of the factory
1305      * associated with the pool. If the object fails to validate, it will be
1306      * removed from the pool and destroyed, and a new attempt will be made to
1307      * borrow an object from the pool.
1308      *
1309      * @param testOnBorrow  {@code true} if objects should be validated
1310      *                      before being returned from the
1311      *                      {@code borrowObject()} method
1312      *
1313      * @see #getTestOnBorrow
1314      */
1315     public final void setTestOnBorrow(final boolean testOnBorrow) {
1316         this.testOnBorrow = testOnBorrow;
1317     }
1318 
1319     /**
1320      * Sets whether objects created for the pool will be validated before
1321      * being returned from the {@code borrowObject()} method. Validation is
1322      * performed by the {@code validateObject()} method of the factory
1323      * associated with the pool. If the object fails to validate, then
1324      * {@code borrowObject()} will fail.
1325      *
1326      * @param testOnCreate  {@code true} if newly created objects should be
1327      *                      validated before being returned from the
1328      *                      {@code borrowObject()} method
1329      *
1330      * @see #getTestOnCreate
1331      *
1332      * @since 2.2
1333      */
1334     public final void setTestOnCreate(final boolean testOnCreate) {
1335         this.testOnCreate = testOnCreate;
1336     }
1337 
1338     /**
1339      * Sets whether objects borrowed from the pool will be validated when
1340      * they are returned to the pool via the {@code returnObject()} method.
1341      * Validation is performed by the {@code validateObject()} method of
1342      * the factory associated with the pool. Returning objects that fail validation
1343      * are destroyed rather then being returned the pool.
1344      *
1345      * @param testOnReturn {@code true} if objects are validated on
1346      *                     return to the pool via the
1347      *                     {@code returnObject()} method
1348      *
1349      * @see #getTestOnReturn
1350      */
1351     public final void setTestOnReturn(final boolean testOnReturn) {
1352         this.testOnReturn = testOnReturn;
1353     }
1354 
1355     /**
1356      * Sets whether objects sitting idle in the pool will be validated by the
1357      * idle object evictor (if any - see
1358      * {@link #setTimeBetweenEvictionRuns(Duration)}). Validation is performed
1359      * by the {@code validateObject()} method of the factory associated
1360      * with the pool. If the object fails to validate, it will be removed from
1361      * the pool and destroyed.  Note that setting this property has no effect
1362      * unless the idle object evictor is enabled by setting
1363      * {@code timeBetweenEvictionRunsMillis} to a positive value.
1364      *
1365      * @param testWhileIdle
1366      *            {@code true} so objects will be validated by the evictor
1367      *
1368      * @see #getTestWhileIdle
1369      * @see #setTimeBetweenEvictionRuns
1370      */
1371     public final void setTestWhileIdle(final boolean testWhileIdle) {
1372         this.testWhileIdle = testWhileIdle;
1373     }
1374 
1375     /**
1376      * Sets the number of milliseconds to sleep between runs of the idle object evictor thread.
1377      * <ul>
1378      * <li>When positive, the idle object evictor thread starts.</li>
1379      * <li>When non-positive, no idle object evictor thread runs.</li>
1380      * </ul>
1381      *
1382      * @param timeBetweenEvictionRuns
1383      *            duration to sleep between evictor runs
1384      *
1385      * @see #getTimeBetweenEvictionRunsMillis
1386      * @since 2.10.0
1387      */
1388     public final void setTimeBetweenEvictionRuns(final Duration timeBetweenEvictionRuns) {
1389         this.timeBetweenEvictionRuns = timeBetweenEvictionRuns;
1390         startEvictor(this.timeBetweenEvictionRuns);
1391     }
1392 
1393     /**
1394      * Sets the number of milliseconds to sleep between runs of the idle object evictor thread.
1395      * <ul>
1396      * <li>When positive, the idle object evictor thread starts.</li>
1397      * <li>When non-positive, no idle object evictor thread runs.</li>
1398      * </ul>
1399      *
1400      * @param timeBetweenEvictionRunsMillis
1401      *            number of milliseconds to sleep between evictor runs
1402      *
1403      * @see #getTimeBetweenEvictionRunsMillis
1404      * @deprecated Use {@link #setTimeBetweenEvictionRuns(Duration)}.
1405      */
1406     @Deprecated
1407     public final void setTimeBetweenEvictionRunsMillis(final long timeBetweenEvictionRunsMillis) {
1408         this.timeBetweenEvictionRuns = Duration.ofMillis(timeBetweenEvictionRunsMillis);
1409         startEvictor(timeBetweenEvictionRuns);
1410     }
1411 
1412     /**
1413      * <p>Starts the evictor with the given delay. If there is an evictor
1414      * running when this method is called, it is stopped and replaced with a
1415      * new evictor with the specified delay.</p>
1416      *
1417      * <p>This method needs to be final, since it is called from a constructor.
1418      * See POOL-195.</p>
1419      *
1420      * @param delay time in milliseconds before start and between eviction runs
1421      */
1422     final void startEvictor(final Duration delay) {
1423         synchronized (evictionLock) {
1424             final boolean isPositiverDelay = PoolImplUtils.isPositive(delay);
1425             if (evictor == null) { // Starting evictor for the first time or after a cancel
1426                 if (isPositiverDelay) {   // Starting new evictor
1427                     evictor = new Evictor();
1428                     EvictionTimer.schedule(evictor, delay, delay);
1429                 }
1430             } else {  // Stop or restart of existing evictor
1431                 if (isPositiverDelay) { // Restart
1432                     synchronized (EvictionTimer.class) { // Ensure no cancel can happen between cancel / schedule calls
1433                         EvictionTimer.cancel(evictor, evictorShutdownTimeout, true);
1434                         evictor = null;
1435                         evictionIterator = null;
1436                         evictor = new Evictor();
1437                         EvictionTimer.schedule(evictor, delay, delay);
1438                     }
1439                 } else { // Stopping evictor
1440                     EvictionTimer.cancel(evictor, evictorShutdownTimeout, false);
1441                 }
1442             }
1443         }
1444     }
1445 
1446 
1447 
1448     // Inner classes
1449 
1450     /**
1451      * Stops the evictor.
1452      */
1453     void stopEvictor() {
1454         startEvictor(Duration.ofMillis(-1L));
1455     }
1456 
1457     /**
1458      * Swallows an exception and notifies the configured listener for swallowed
1459      * exceptions queue.
1460      *
1461      * @param swallowException exception to be swallowed
1462      */
1463     final void swallowException(final Exception swallowException) {
1464         final SwallowedExceptionListener listener = getSwallowedExceptionListener();
1465 
1466         if (listener == null) {
1467             return;
1468         }
1469 
1470         try {
1471             listener.onSwallowException(swallowException);
1472         } catch (final VirtualMachineError e) {
1473             throw e;
1474         } catch (final Throwable t) {
1475             // Ignore. Enjoy the irony.
1476         }
1477     }
1478 
1479     @Override
1480     protected void toStringAppendFields(final StringBuilder builder) {
1481         builder.append("maxTotal=");
1482         builder.append(maxTotal);
1483         builder.append(", blockWhenExhausted=");
1484         builder.append(blockWhenExhausted);
1485         builder.append(", maxWaitMillis=");
1486         builder.append(maxWait);
1487         builder.append(", lifo=");
1488         builder.append(lifo);
1489         builder.append(", fairness=");
1490         builder.append(fairness);
1491         builder.append(", testOnCreate=");
1492         builder.append(testOnCreate);
1493         builder.append(", testOnBorrow=");
1494         builder.append(testOnBorrow);
1495         builder.append(", testOnReturn=");
1496         builder.append(testOnReturn);
1497         builder.append(", testWhileIdle=");
1498         builder.append(testWhileIdle);
1499         builder.append(", timeBetweenEvictionRunsMillis=");
1500         builder.append(timeBetweenEvictionRuns);
1501         builder.append(", numTestsPerEvictionRun=");
1502         builder.append(numTestsPerEvictionRun);
1503         builder.append(", minEvictableIdleTimeMillis=");
1504         builder.append(minEvictableIdleTime);
1505         builder.append(", softMinEvictableIdleTimeMillis=");
1506         builder.append(softMinEvictableIdleTime);
1507         builder.append(", evictionPolicy=");
1508         builder.append(evictionPolicy);
1509         builder.append(", closeLock=");
1510         builder.append(closeLock);
1511         builder.append(", closed=");
1512         builder.append(closed);
1513         builder.append(", evictionLock=");
1514         builder.append(evictionLock);
1515         builder.append(", evictor=");
1516         builder.append(evictor);
1517         builder.append(", evictionIterator=");
1518         builder.append(evictionIterator);
1519         builder.append(", factoryClassLoader=");
1520         builder.append(factoryClassLoader);
1521         builder.append(", oname=");
1522         builder.append(objectName);
1523         builder.append(", creationStackTrace=");
1524         builder.append(creationStackTrace);
1525         builder.append(", borrowedCount=");
1526         builder.append(borrowedCount);
1527         builder.append(", returnedCount=");
1528         builder.append(returnedCount);
1529         builder.append(", createdCount=");
1530         builder.append(createdCount);
1531         builder.append(", destroyedCount=");
1532         builder.append(destroyedCount);
1533         builder.append(", destroyedByEvictorCount=");
1534         builder.append(destroyedByEvictorCount);
1535         builder.append(", destroyedByBorrowValidationCount=");
1536         builder.append(destroyedByBorrowValidationCount);
1537         builder.append(", activeTimes=");
1538         builder.append(activeTimes);
1539         builder.append(", idleTimes=");
1540         builder.append(idleTimes);
1541         builder.append(", waitTimes=");
1542         builder.append(waitTimes);
1543         builder.append(", maxBorrowWaitTimeMillis=");
1544         builder.append(maxBorrowWaitTimeMillis);
1545         builder.append(", swallowedExceptionListener=");
1546         builder.append(swallowedExceptionListener);
1547     }
1548 
1549     /**
1550      * Updates statistics after an object is borrowed from the pool.
1551      *
1552      * @param p object borrowed from the pool
1553      * @param waitTime time (in milliseconds) that the borrowing thread had to wait
1554      */
1555     final void updateStatsBorrow(final PooledObject<T> p, final Duration waitTime) {
1556         borrowedCount.incrementAndGet();
1557         idleTimes.add(p.getIdleTime());
1558         waitTimes.add(waitTime);
1559         final long waitTimeMillis = waitTime.toMillis();
1560 
1561         // lock-free optimistic-locking maximum
1562         long currentMaxMillis;
1563         do {
1564             currentMaxMillis = maxBorrowWaitTimeMillis.get();
1565             if (currentMaxMillis >= waitTimeMillis) {
1566                 break;
1567             }
1568         } while (!maxBorrowWaitTimeMillis.compareAndSet(currentMaxMillis, waitTimeMillis));
1569     }
1570 
1571     /**
1572      * Updates statistics after an object is returned to the pool.
1573      *
1574      * @param activeTime the amount of time (in milliseconds) that the returning
1575      * object was checked out
1576      */
1577     final void updateStatsReturn(final Duration activeTime) {
1578         returnedCount.incrementAndGet();
1579         activeTimes.add(activeTime);
1580     }
1581 
1582 
1583 }