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.tomcat.dbcp.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.util.Arrays;
26 import java.util.Deque;
27 import java.util.Iterator;
28 import java.util.TimerTask;
29 import java.util.concurrent.ScheduledFuture;
30 import java.util.concurrent.TimeUnit;
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.tomcat.dbcp.pool2.BaseObject;
42 import org.apache.tomcat.dbcp.pool2.PooledObject;
43 import org.apache.tomcat.dbcp.pool2.PooledObjectState;
44 import org.apache.tomcat.dbcp.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     // Constants
60     /**
61      * The size of the caches used to store historical data for some attributes
62      * so that rolling means may be calculated.
63      */

64     public static final int MEAN_TIMING_STATS_CACHE_SIZE = 100;
65
66     private static final String EVICTION_POLICY_TYPE_NAME = EvictionPolicy.class.getName();
67
68     // Configuration attributes
69     private volatile int maxTotal =
70             GenericKeyedObjectPoolConfig.DEFAULT_MAX_TOTAL;
71     private volatile boolean blockWhenExhausted =
72             BaseObjectPoolConfig.DEFAULT_BLOCK_WHEN_EXHAUSTED;
73     private volatile long maxWaitMillis =
74             BaseObjectPoolConfig.DEFAULT_MAX_WAIT_MILLIS;
75     private volatile boolean lifo = BaseObjectPoolConfig.DEFAULT_LIFO;
76     private final boolean fairness;
77     private volatile boolean testOnCreate =
78             BaseObjectPoolConfig.DEFAULT_TEST_ON_CREATE;
79     private volatile boolean testOnBorrow =
80             BaseObjectPoolConfig.DEFAULT_TEST_ON_BORROW;
81     private volatile boolean testOnReturn =
82             BaseObjectPoolConfig.DEFAULT_TEST_ON_RETURN;
83     private volatile boolean testWhileIdle =
84             BaseObjectPoolConfig.DEFAULT_TEST_WHILE_IDLE;
85     private volatile long timeBetweenEvictionRunsMillis =
86             BaseObjectPoolConfig.DEFAULT_TIME_BETWEEN_EVICTION_RUNS_MILLIS;
87     private volatile int numTestsPerEvictionRun =
88             BaseObjectPoolConfig.DEFAULT_NUM_TESTS_PER_EVICTION_RUN;
89     private volatile long minEvictableIdleTimeMillis =
90             BaseObjectPoolConfig.DEFAULT_MIN_EVICTABLE_IDLE_TIME_MILLIS;
91     private volatile long softMinEvictableIdleTimeMillis =
92             BaseObjectPoolConfig.DEFAULT_SOFT_MIN_EVICTABLE_IDLE_TIME_MILLIS;
93     private volatile EvictionPolicy<T> evictionPolicy;
94     private volatile long evictorShutdownTimeoutMillis =
95             BaseObjectPoolConfig.DEFAULT_EVICTOR_SHUTDOWN_TIMEOUT_MILLIS;
96
97
98     // Internal (primarily state) attributes
99     final Object closeLock = new Object();
100     volatile boolean closed = false;
101     final Object evictionLock = new Object();
102     private Evictor evictor = null// @GuardedBy("evictionLock")
103     EvictionIterator evictionIterator = null// @GuardedBy("evictionLock")
104     /*
105      * Class loader for evictor thread to use since, in a JavaEE or similar
106      * environment, the context class loader for the evictor thread may not have
107      * visibility of the correct factory. See POOL-161. Uses a weak reference to
108      * avoid potential memory leaks if the Pool is discarded rather than closed.
109      */

110     private final WeakReference<ClassLoader> factoryClassLoader;
111
112
113     // Monitoring (primarily JMX) attributes
114     private final ObjectName objectName;
115     private final String creationStackTrace;
116     private final AtomicLong borrowedCount = new AtomicLong(0);
117     private final AtomicLong returnedCount = new AtomicLong(0);
118     final AtomicLong createdCount = new AtomicLong(0);
119     final AtomicLong destroyedCount = new AtomicLong(0);
120     final AtomicLong destroyedByEvictorCount = new AtomicLong(0);
121     final AtomicLong destroyedByBorrowValidationCount = new AtomicLong(0);
122     private final StatsStore activeTimes = new StatsStore(MEAN_TIMING_STATS_CACHE_SIZE);
123     private final StatsStore idleTimes = new StatsStore(MEAN_TIMING_STATS_CACHE_SIZE);
124     private final StatsStore waitTimes = new StatsStore(MEAN_TIMING_STATS_CACHE_SIZE);
125     private final AtomicLong maxBorrowWaitTimeMillis = new AtomicLong(0L);
126     private volatile SwallowedExceptionListener swallowedExceptionListener = null;
127
128
129     /**
130      * Handles JMX registration (if required) and the initialization required for
131      * monitoring.
132      *
133      * @param config        Pool configuration
134      * @param jmxNameBase   The default base JMX name for the new pool unless
135      *                      overridden by the config
136      * @param jmxNamePrefix Prefix to be used for JMX name for the new pool
137      */

138     public BaseGenericObjectPool(final BaseObjectPoolConfig<T> config,
139             final String jmxNameBase, final String jmxNamePrefix) {
140         if (config.getJmxEnabled()) {
141             this.objectName = jmxRegister(config, jmxNameBase, jmxNamePrefix);
142         } else {
143             this.objectName = null;
144         }
145
146         // Populate the creation stack trace
147         this.creationStackTrace = getStackTrace(new Exception());
148
149         // save the current TCCL (if any) to be used later by the evictor Thread
150         final ClassLoader cl = Thread.currentThread().getContextClassLoader();
151         if (cl == null) {
152             factoryClassLoader = null;
153         } else {
154             factoryClassLoader = new WeakReference<>(cl);
155         }
156
157         fairness = config.getFairness();
158     }
159
160
161     /**
162      * Returns the maximum number of objects that can be allocated by the pool
163      * (checked out to clients, or idle awaiting checkout) at a given time. When
164      * negative, there is no limit to the number of objects that can be
165      * managed by the pool at one time.
166      *
167      * @return the cap on the total number of object instances managed by the
168      *         pool.
169      *
170      * @see #setMaxTotal
171      */

172     public final int getMaxTotal() {
173         return maxTotal;
174     }
175
176     /**
177      * Sets the cap on the number of objects that can be allocated by the pool
178      * (checked out to clients, or idle awaiting checkout) at a given time. Use
179      * a negative value for no limit.
180      *
181      * @param maxTotal  The cap on the total number of object instances managed
182      *                  by the pool. Negative values mean that there is no limit
183      *                  to the number of objects allocated by the pool.
184      *
185      * @see #getMaxTotal
186      */

187     public final void setMaxTotal(final int maxTotal) {
188         this.maxTotal = maxTotal;
189     }
190
191     /**
192      * Returns whether to block when the <code>borrowObject()</code> method is
193      * invoked when the pool is exhausted (the maximum number of "active"
194      * objects has been reached).
195      *
196      * @return <code>true</code> if <code>borrowObject()</code> should block
197      *         when the pool is exhausted
198      *
199      * @see #setBlockWhenExhausted
200      */

201     public final boolean getBlockWhenExhausted() {
202         return blockWhenExhausted;
203     }
204
205     /**
206      * Sets whether to block when the <code>borrowObject()</code> method is
207      * invoked when the pool is exhausted (the maximum number of "active"
208      * objects has been reached).
209      *
210      * @param blockWhenExhausted    <code>true</code> if
211      *                              <code>borrowObject()</code> should block
212      *                              when the pool is exhausted
213      *
214      * @see #getBlockWhenExhausted
215      */

216     public final void setBlockWhenExhausted(final boolean blockWhenExhausted) {
217         this.blockWhenExhausted = blockWhenExhausted;
218     }
219
220     protected void setConfig(final BaseObjectPoolConfig<T> conf) {
221         setLifo(conf.getLifo());
222         setMaxWaitMillis(conf.getMaxWaitMillis());
223         setBlockWhenExhausted(conf.getBlockWhenExhausted());
224         setTestOnCreate(conf.getTestOnCreate());
225         setTestOnBorrow(conf.getTestOnBorrow());
226         setTestOnReturn(conf.getTestOnReturn());
227         setTestWhileIdle(conf.getTestWhileIdle());
228         setNumTestsPerEvictionRun(conf.getNumTestsPerEvictionRun());
229         setMinEvictableIdleTimeMillis(conf.getMinEvictableIdleTimeMillis());
230         setTimeBetweenEvictionRunsMillis(conf.getTimeBetweenEvictionRunsMillis());
231         setSoftMinEvictableIdleTimeMillis(conf.getSoftMinEvictableIdleTimeMillis());
232         final EvictionPolicy<T> policy = conf.getEvictionPolicy();
233         if (policy == null) {
234             // Use the class name (pre-2.6.0 compatible)
235             setEvictionPolicyClassName(conf.getEvictionPolicyClassName());
236         } else {
237             // Otherwise, use the class (2.6.0 feature)
238             setEvictionPolicy(policy);
239         }
240         setEvictorShutdownTimeoutMillis(conf.getEvictorShutdownTimeoutMillis());
241     }
242
243     /**
244      * Returns the maximum amount of time (in milliseconds) the
245      * <code>borrowObject()</code> method should block before throwing an
246      * exception when the pool is exhausted and
247      * {@link #getBlockWhenExhausted} is true. When less than 0, the
248      * <code>borrowObject()</code> method may block indefinitely.
249      *
250      * @return the maximum number of milliseconds <code>borrowObject()</code>
251      *         will block.
252      *
253      * @see #setMaxWaitMillis
254      * @see #setBlockWhenExhausted
255      */

256     public final long getMaxWaitMillis() {
257         return maxWaitMillis;
258     }
259
260     /**
261      * Sets the maximum amount of time (in milliseconds) the
262      * <code>borrowObject()</code> method should block before throwing an
263      * exception when the pool is exhausted and
264      * {@link #getBlockWhenExhausted} is true. When less than 0, the
265      * <code>borrowObject()</code> method may block indefinitely.
266      *
267      * @param maxWaitMillis the maximum number of milliseconds
268      *                      <code>borrowObject()</code> will block or negative
269      *                      for indefinitely.
270      *
271      * @see #getMaxWaitMillis
272      * @see #setBlockWhenExhausted
273      */

274     public final void setMaxWaitMillis(final long maxWaitMillis) {
275         this.maxWaitMillis = maxWaitMillis;
276     }
277
278     /**
279      * Returns whether the pool has LIFO (last in, first out) behaviour with
280      * respect to idle objects - always returning the most recently used object
281      * from the pool, or as a FIFO (first in, first out) queue, where the pool
282      * always returns the oldest object in the idle object pool.
283      *
284      * @return <code>true</code> if the pool is configured with LIFO behaviour
285      *         or <code>false</code> if the pool is configured with FIFO
286      *         behaviour
287      *
288      * @see #setLifo
289      */

290     public final boolean getLifo() {
291         return lifo;
292     }
293
294     /**
295      * Returns whether or not the pool serves threads waiting to borrow objects fairly.
296      * True means that waiting threads are served as if waiting in a FIFO queue.
297      *
298      * @return <code>true</code> if waiting threads are to be served
299      *             by the pool in arrival order
300      */

301     public final boolean getFairness() {
302         return fairness;
303     }
304
305     /**
306      * Sets whether the pool has LIFO (last in, first out) behaviour with
307      * respect to idle objects - always returning the most recently used object
308      * from the pool, or as a FIFO (first in, first out) queue, where the pool
309      * always returns the oldest object in the idle object pool.
310      *
311      * @param lifo  <code>true</code> if the pool is to be configured with LIFO
312      *              behaviour or <code>false</code> if the pool is to be
313      *              configured with FIFO behaviour
314      *
315      * @see #getLifo()
316      */

317     public final void setLifo(final boolean lifo) {
318         this.lifo = lifo;
319     }
320
321     /**
322      * Returns whether objects created for the pool will be validated before
323      * being returned from the <code>borrowObject()</code> method. Validation is
324      * performed by the <code>validateObject()</code> method of the factory
325      * associated with the pool. If the object fails to validate, then
326      * <code>borrowObject()</code> will fail.
327      *
328      * @return <code>true</code> if newly created objects are validated before
329      *         being returned from the <code>borrowObject()</code> method
330      *
331      * @see #setTestOnCreate
332      *
333      * @since 2.2
334      */

335     public final boolean getTestOnCreate() {
336         return testOnCreate;
337     }
338
339     /**
340      * Sets whether objects created for the pool will be validated before
341      * being returned from the <code>borrowObject()</code> method. Validation is
342      * performed by the <code>validateObject()</code> method of the factory
343      * associated with the pool. If the object fails to validate, then
344      * <code>borrowObject()</code> will fail.
345      *
346      * @param testOnCreate  <code>true</code> if newly created objects should be
347      *                      validated before being returned from the
348      *                      <code>borrowObject()</code> method
349      *
350      * @see #getTestOnCreate
351      *
352      * @since 2.2
353      */

354     public final void setTestOnCreate(final boolean testOnCreate) {
355         this.testOnCreate = testOnCreate;
356     }
357
358     /**
359      * Returns whether objects borrowed from the pool will be validated before
360      * being returned from the <code>borrowObject()</code> method. Validation is
361      * performed by the <code>validateObject()</code> method of the factory
362      * associated with the pool. If the object fails to validate, it will be
363      * removed from the pool and destroyed, and a new attempt will be made to
364      * borrow an object from the pool.
365      *
366      * @return <code>true</code> if objects are validated before being returned
367      *         from the <code>borrowObject()</code> method
368      *
369      * @see #setTestOnBorrow
370      */

371     public final boolean getTestOnBorrow() {
372         return testOnBorrow;
373     }
374
375     /**
376      * Sets whether objects borrowed from the pool will be validated before
377      * being returned from the <code>borrowObject()</code> method. Validation is
378      * performed by the <code>validateObject()</code> method of the factory
379      * associated with the pool. If the object fails to validate, it will be
380      * removed from the pool and destroyed, and a new attempt will be made to
381      * borrow an object from the pool.
382      *
383      * @param testOnBorrow  <code>true</code> if objects should be validated
384      *                      before being returned from the
385      *                      <code>borrowObject()</code> method
386      *
387      * @see #getTestOnBorrow
388      */

389     public final void setTestOnBorrow(final boolean testOnBorrow) {
390         this.testOnBorrow = testOnBorrow;
391     }
392
393     /**
394      * Returns whether objects borrowed from the pool will be validated when
395      * they are returned to the pool via the <code>returnObject()</code> method.
396      * Validation is performed by the <code>validateObject()</code> method of
397      * the factory associated with the pool. Returning objects that fail validation
398      * are destroyed rather then being returned the pool.
399      *
400      * @return <code>true</code> if objects are validated on return to
401      *         the pool via the <code>returnObject()</code> method
402      *
403      * @see #setTestOnReturn
404      */

405     public final boolean getTestOnReturn() {
406         return testOnReturn;
407     }
408
409     /**
410      * Sets whether objects borrowed from the pool will be validated when
411      * they are returned to the pool via the <code>returnObject()</code> method.
412      * Validation is performed by the <code>validateObject()</code> method of
413      * the factory associated with the pool. Returning objects that fail validation
414      * are destroyed rather then being returned the pool.
415      *
416      * @param testOnReturn <code>true</code> if objects are validated on
417      *                     return to the pool via the
418      *                     <code>returnObject()</code> method
419      *
420      * @see #getTestOnReturn
421      */

422     public final void setTestOnReturn(final boolean testOnReturn) {
423         this.testOnReturn = testOnReturn;
424     }
425
426     /**
427      * Returns whether objects sitting idle in the pool will be validated by the
428      * idle object evictor (if any - see
429      * {@link #setTimeBetweenEvictionRunsMillis(long)}). Validation is performed
430      * by the <code>validateObject()</code> method of the factory associated
431      * with the pool. If the object fails to validate, it will be removed from
432      * the pool and destroyed.
433      *
434      * @return <code>true</code> if objects will be validated by the evictor
435      *
436      * @see #setTestWhileIdle
437      * @see #setTimeBetweenEvictionRunsMillis
438      */

439     public final boolean getTestWhileIdle() {
440         return testWhileIdle;
441     }
442
443     /**
444      * Returns whether objects sitting idle in the pool will be validated by the
445      * idle object evictor (if any - see
446      * {@link #setTimeBetweenEvictionRunsMillis(long)}). Validation is performed
447      * by the <code>validateObject()</code> method of the factory associated
448      * with the pool. If the object fails to validate, it will be removed from
449      * the pool and destroyed.  Note that setting this property has no effect
450      * unless the idle object evictor is enabled by setting
451      * <code>timeBetweenEvictionRunsMillis</code> to a positive value.
452      *
453      * @param testWhileIdle
454      *            <code>true</code> so objects will be validated by the evictor
455      *
456      * @see #getTestWhileIdle
457      * @see #setTimeBetweenEvictionRunsMillis
458      */

459     public final void setTestWhileIdle(final boolean testWhileIdle) {
460         this.testWhileIdle = testWhileIdle;
461     }
462
463     /**
464      * Returns the number of milliseconds to sleep between runs of the idle
465      * object evictor thread. When non-positive, no idle object evictor thread
466      * will be run.
467      *
468      * @return number of milliseconds to sleep between evictor runs
469      *
470      * @see #setTimeBetweenEvictionRunsMillis
471      */

472     public final long getTimeBetweenEvictionRunsMillis() {
473         return timeBetweenEvictionRunsMillis;
474     }
475
476     /**
477      * Sets the number of milliseconds to sleep between runs of the idle object evictor thread.
478      * <ul>
479      * <li>When positive, the idle object evictor thread starts.</li>
480      * <li>When non-positive, no idle object evictor thread runs.</li>
481      * </ul>
482      *
483      * @param timeBetweenEvictionRunsMillis
484      *            number of milliseconds to sleep between evictor runs
485      *
486      * @see #getTimeBetweenEvictionRunsMillis
487      */

488     public final void setTimeBetweenEvictionRunsMillis(
489             final long timeBetweenEvictionRunsMillis) {
490         this.timeBetweenEvictionRunsMillis = timeBetweenEvictionRunsMillis;
491         startEvictor(timeBetweenEvictionRunsMillis);
492     }
493
494     /**
495      * Returns the maximum number of objects to examine during each run (if any)
496      * of the idle object evictor thread. When positive, the number of tests
497      * performed for a run will be the minimum of the configured value and the
498      * number of idle instances in the pool. When negative, the number of tests
499      * performed will be <code>ceil({@link #getNumIdle}/
500      * abs({@link #getNumTestsPerEvictionRun}))</code> which means that when the
501      * value is <code>-n</code> roughly one nth of the idle objects will be
502      * tested per run.
503      *
504      * @return max number of objects to examine during each evictor run
505      *
506      * @see #setNumTestsPerEvictionRun
507      * @see #setTimeBetweenEvictionRunsMillis
508      */

509     public final int getNumTestsPerEvictionRun() {
510         return numTestsPerEvictionRun;
511     }
512
513     /**
514      * Sets the maximum number of objects to examine during each run (if any)
515      * of the idle object evictor thread. When positive, the number of tests
516      * performed for a run will be the minimum of the configured value and the
517      * number of idle instances in the pool. When negative, the number of tests
518      * performed will be <code>ceil({@link #getNumIdle}/
519      * abs({@link #getNumTestsPerEvictionRun}))</code> which means that when the
520      * value is <code>-n</code> roughly one nth of the idle objects will be
521      * tested per run.
522      *
523      * @param numTestsPerEvictionRun
524      *            max number of objects to examine during each evictor run
525      *
526      * @see #getNumTestsPerEvictionRun
527      * @see #setTimeBetweenEvictionRunsMillis
528      */

529     public final void setNumTestsPerEvictionRun(final int numTestsPerEvictionRun) {
530         this.numTestsPerEvictionRun = numTestsPerEvictionRun;
531     }
532
533     /**
534      * Returns the minimum amount of time an object may sit idle in the pool
535      * before it is eligible for eviction by the idle object evictor (if any -
536      * see {@link #setTimeBetweenEvictionRunsMillis(long)}). When non-positive,
537      * no objects will be evicted from the pool due to idle time alone.
538      *
539      * @return minimum amount of time an object may sit idle in the pool before
540      *         it is eligible for eviction
541      *
542      * @see #setMinEvictableIdleTimeMillis
543      * @see #setTimeBetweenEvictionRunsMillis
544      */

545     public final long getMinEvictableIdleTimeMillis() {
546         return minEvictableIdleTimeMillis;
547     }
548
549     /**
550      * Sets the minimum amount of time an object may sit idle in the pool
551      * before it is eligible for eviction by the idle object evictor (if any -
552      * see {@link #setTimeBetweenEvictionRunsMillis(long)}). When non-positive,
553      * no objects will be evicted from the pool due to idle time alone.
554      *
555      * @param minEvictableIdleTimeMillis
556      *            minimum amount of time an object may sit idle in the pool
557      *            before it is eligible for eviction
558      *
559      * @see #getMinEvictableIdleTimeMillis
560      * @see #setTimeBetweenEvictionRunsMillis
561      */

562     public final void setMinEvictableIdleTimeMillis(
563             final long minEvictableIdleTimeMillis) {
564         this.minEvictableIdleTimeMillis = minEvictableIdleTimeMillis;
565     }
566
567     /**
568      * Returns the minimum amount of time an object may sit idle in the pool
569      * before it is eligible for eviction by the idle object evictor (if any -
570      * see {@link #setTimeBetweenEvictionRunsMillis(long)}),
571      * with the extra condition that at least <code>minIdle</code> object
572      * instances remain in the pool. This setting is overridden by
573      * {@link #getMinEvictableIdleTimeMillis} (that is, if
574      * {@link #getMinEvictableIdleTimeMillis} is positive, then
575      * {@link #getSoftMinEvictableIdleTimeMillis} is ignored).
576      *
577      * @return minimum amount of time an object may sit idle in the pool before
578      *         it is eligible for eviction if minIdle instances are available
579      *
580      * @see #setSoftMinEvictableIdleTimeMillis
581      */

582     public final long getSoftMinEvictableIdleTimeMillis() {
583         return softMinEvictableIdleTimeMillis;
584     }
585
586     /**
587      * Sets the minimum amount of time an object may sit idle in the pool
588      * before it is eligible for eviction by the idle object evictor (if any -
589      * see {@link #setTimeBetweenEvictionRunsMillis(long)}),
590      * with the extra condition that at least <code>minIdle</code> object
591      * instances remain in the pool. This setting is overridden by
592      * {@link #getMinEvictableIdleTimeMillis} (that is, if
593      * {@link #getMinEvictableIdleTimeMillis} is positive, then
594      * {@link #getSoftMinEvictableIdleTimeMillis} is ignored).
595      *
596      * @param softMinEvictableIdleTimeMillis
597      *            minimum amount of time an object may sit idle in the pool
598      *            before it is eligible for eviction if minIdle instances are
599      *            available
600      *
601      * @see #getSoftMinEvictableIdleTimeMillis
602      */

603     public final void setSoftMinEvictableIdleTimeMillis(
604             final long softMinEvictableIdleTimeMillis) {
605         this.softMinEvictableIdleTimeMillis = softMinEvictableIdleTimeMillis;
606     }
607
608     /**
609      * Returns the name of the {@link EvictionPolicy} implementation that is
610      * used by this pool.
611      *
612      * @return  The fully qualified class name of the {@link EvictionPolicy}
613      *
614      * @see #setEvictionPolicyClassName(String)
615      */

616     public final String getEvictionPolicyClassName() {
617         return evictionPolicy.getClass().getName();
618     }
619
620     /**
621      * Sets the eviction policy for this pool.
622      *
623      * @param evictionPolicy
624      *            the eviction policy for this pool.
625      * @since 2.6.0
626      */

627     public void setEvictionPolicy(final EvictionPolicy<T> evictionPolicy) {
628         this.evictionPolicy = evictionPolicy;
629     }
630
631     /**
632      * Sets the name of the {@link EvictionPolicy} implementation that is used by this pool. The Pool will attempt to
633      * load the class using the given class loader. If that fails, use the class loader for the {@link EvictionPolicy}
634      * interface.
635      *
636      * @param evictionPolicyClassName
637      *            the fully qualified class name of the new eviction policy
638      * @param classLoader
639      *            the class loader to load the given {@code evictionPolicyClassName}.
640      *
641      * @see #getEvictionPolicyClassName()
642      * @since 2.6.0 If loading the class using the given class loader fails, use the class loader for the
643      *        {@link EvictionPolicy} interface.
644      */

645     public final void setEvictionPolicyClassName(final String evictionPolicyClassName, final ClassLoader classLoader) {
646         // Getting epClass here and now best matches the caller's environment
647         final Class<?> epClass = EvictionPolicy.class;
648         final ClassLoader epClassLoader = epClass.getClassLoader();
649         try {
650             try {
651                 setEvictionPolicy(evictionPolicyClassName, classLoader);
652             } catch (final ClassCastException | ClassNotFoundException e) {
653                 setEvictionPolicy(evictionPolicyClassName, epClassLoader);
654             }
655         } catch (final ClassCastException e) {
656             throw new IllegalArgumentException("Class " + evictionPolicyClassName + " from class loaders ["
657                     + classLoader + ", " + epClassLoader + "] do not implement " + EVICTION_POLICY_TYPE_NAME);
658         } catch (final ClassNotFoundException | InstantiationException | IllegalAccessException
659                 | InvocationTargetException | NoSuchMethodException e) {
660             final String exMessage = "Unable to create " + EVICTION_POLICY_TYPE_NAME + " instance of type "
661                     + evictionPolicyClassName;
662             throw new IllegalArgumentException(exMessage, e);
663         }
664     }
665
666     @SuppressWarnings("unchecked")
667     private void setEvictionPolicy(final String className, final ClassLoader classLoader)
668             throws ClassNotFoundException, InstantiationException, IllegalAccessException, InvocationTargetException, NoSuchMethodException {
669         final Class<?> clazz = Class.forName(className, true, classLoader);
670         final Object policy = clazz.getConstructor().newInstance();
671         this.evictionPolicy = (EvictionPolicy<T>) policy;
672     }
673
674     /**
675      * Sets the name of the {@link EvictionPolicy} implementation that is used by this pool. The Pool will attempt to
676      * load the class using the thread context class loader. If that fails, the use the class loader for the
677      * {@link EvictionPolicy} interface.
678      *
679      * @param evictionPolicyClassName
680      *            the fully qualified class name of the new eviction policy
681      *
682      * @see #getEvictionPolicyClassName()
683      * @since 2.6.0 If loading the class using the thread context class loader fails, use the class loader for the
684      *        {@link EvictionPolicy} interface.
685      */

686     public final void setEvictionPolicyClassName(final String evictionPolicyClassName) {
687         setEvictionPolicyClassName(evictionPolicyClassName, Thread.currentThread().getContextClassLoader());
688     }
689
690     /**
691      * Gets the timeout that will be used when waiting for the Evictor to
692      * shutdown if this pool is closed and it is the only pool still using the
693      * the value for the Evictor.
694      *
695      * @return  The timeout in milliseconds that will be used while waiting for
696      *          the Evictor to shut down.
697      */

698     public final long getEvictorShutdownTimeoutMillis() {
699         return evictorShutdownTimeoutMillis;
700     }
701
702     /**
703      * Sets the timeout that will be used when waiting for the Evictor to
704      * shutdown if this pool is closed and it is the only pool still using the
705      * the value for the Evictor.
706      *
707      * @param evictorShutdownTimeoutMillis  the timeout in milliseconds that
708      *                                      will be used while waiting for the
709      *                                      Evictor to shut down.
710      */

711     public final void setEvictorShutdownTimeoutMillis(
712             final long evictorShutdownTimeoutMillis) {
713         this.evictorShutdownTimeoutMillis = evictorShutdownTimeoutMillis;
714     }
715
716     /**
717      * Closes the pool, destroys the remaining idle objects and, if registered
718      * in JMX, deregisters it.
719      */

720     public abstract void close();
721
722     /**
723      * Has this pool instance been closed.
724      * @return <code>true</code> when this pool has been closed.
725      */

726     public final boolean isClosed() {
727         return closed;
728     }
729
730     /**
731      * <p>Perform <code>numTests</code> idle object eviction tests, evicting
732      * examined objects that meet the criteria for eviction. If
733      * <code>testWhileIdle</code> is true, examined objects are validated
734      * when visited (and removed if invalid); otherwise only objects that
735      * have been idle for more than <code>minEvicableIdleTimeMillis</code>
736      * are removed.</p>
737      *
738      * @throws Exception when there is a problem evicting idle objects.
739      */

740     public abstract void evict() throws Exception;
741
742     /**
743      * Returns the {@link EvictionPolicy} defined for this pool.
744      *
745      * @return the eviction policy
746      * @since 2.4
747      * @since 2.6.0 Changed access from protected to public.
748      */

749     public EvictionPolicy<T> getEvictionPolicy() {
750         return evictionPolicy;
751     }
752
753     /**
754      * Verifies that the pool is open.
755      * @throws IllegalStateException if the pool is closed.
756      */

757     final void assertOpen() throws IllegalStateException {
758         if (isClosed()) {
759             throw new IllegalStateException("Pool not open");
760         }
761     }
762
763     /**
764      * <p>Starts the evictor with the given delay. If there is an evictor
765      * running when this method is called, it is stopped and replaced with a
766      * new evictor with the specified delay.</p>
767      *
768      * <p>This method needs to be final, since it is called from a constructor.
769      * See POOL-195.</p>
770      *
771      * @param delay time in milliseconds before start and between eviction runs
772      */

773     final void startEvictor(final long delay) {
774         synchronized (evictionLock) {
775             EvictionTimer.cancel(evictor, evictorShutdownTimeoutMillis, TimeUnit.MILLISECONDS);
776             evictor = null;
777             evictionIterator = null;
778             if (delay > 0) {
779                 evictor = new Evictor();
780                 EvictionTimer.schedule(evictor, delay, delay);
781             }
782         }
783     }
784
785     /**
786      * Stops the evictor.
787      */

788     void stopEvictor() {
789         startEvictor(-1L);
790     }
791     /**
792      * Tries to ensure that the configured minimum number of idle instances are
793      * available in the pool.
794      * @throws Exception if an error occurs creating idle instances
795      */

796     abstract void ensureMinIdle() throws Exception;
797
798
799     // Monitoring (primarily JMX) related methods
800
801     /**
802      * Provides the name under which the pool has been registered with the
803      * platform MBean server or <code>null</code> if the pool has not been
804      * registered.
805      * @return the JMX name
806      */

807     public final ObjectName getJmxName() {
808         return objectName;
809     }
810
811     /**
812      * Provides the stack trace for the call that created this pool. JMX
813      * registration may trigger a memory leak so it is important that pools are
814      * deregistered when no longer used by calling the {@link #close()} method.
815      * This method is provided to assist with identifying code that creates but
816      * does not close it thereby creating a memory leak.
817      * @return pool creation stack trace
818      */

819     public final String getCreationStackTrace() {
820         return creationStackTrace;
821     }
822
823     /**
824      * The total number of objects successfully borrowed from this pool over the
825      * lifetime of the pool.
826      * @return the borrowed object count
827      */

828     public final long getBorrowedCount() {
829         return borrowedCount.get();
830     }
831
832     /**
833      * The total number of objects returned to this pool over the lifetime of
834      * the pool. This excludes attempts to return the same object multiple
835      * times.
836      * @return the returned object count
837      */

838     public final long getReturnedCount() {
839         return returnedCount.get();
840     }
841
842     /**
843      * The total number of objects created for this pool over the lifetime of
844      * the pool.
845      * @return the created object count
846      */

847     public final long getCreatedCount() {
848         return createdCount.get();
849     }
850
851     /**
852      * The total number of objects destroyed by this pool over the lifetime of
853      * the pool.
854      * @return the destroyed object count
855      */

856     public final long getDestroyedCount() {
857         return destroyedCount.get();
858     }
859
860     /**
861      * The total number of objects destroyed by the evictor associated with this
862      * pool over the lifetime of the pool.
863      * @return the evictor destroyed object count
864      */

865     public final long getDestroyedByEvictorCount() {
866         return destroyedByEvictorCount.get();
867     }
868
869     /**
870      * The total number of objects destroyed by this pool as a result of failing
871      * validation during <code>borrowObject()</code> over the lifetime of the
872      * pool.
873      * @return validation destroyed object count
874      */

875     public final long getDestroyedByBorrowValidationCount() {
876         return destroyedByBorrowValidationCount.get();
877     }
878
879     /**
880      * The mean time objects are active for based on the last {@link
881      * #MEAN_TIMING_STATS_CACHE_SIZE} objects returned to the pool.
882      * @return mean time an object has been checked out from the pool among
883      * recently returned objects
884      */

885     public final long getMeanActiveTimeMillis() {
886         return activeTimes.getMean();
887     }
888
889     /**
890      * The mean time objects are idle for based on the last {@link
891      * #MEAN_TIMING_STATS_CACHE_SIZE} objects borrowed from the pool.
892      * @return mean time an object has been idle in the pool among recently
893      * borrowed objects
894      */

895     public final long getMeanIdleTimeMillis() {
896         return idleTimes.getMean();
897     }
898
899     /**
900      * The mean time threads wait to borrow an object based on the last {@link
901      * #MEAN_TIMING_STATS_CACHE_SIZE} objects borrowed from the pool.
902      * @return mean time in milliseconds that a recently served thread has had
903      * to wait to borrow an object from the pool
904      */

905     public final long getMeanBorrowWaitTimeMillis() {
906         return waitTimes.getMean();
907     }
908
909     /**
910      * The maximum time a thread has waited to borrow objects from the pool.
911      * @return maximum wait time in milliseconds since the pool was created
912      */

913     public final long getMaxBorrowWaitTimeMillis() {
914         return maxBorrowWaitTimeMillis.get();
915     }
916
917     /**
918      * The number of instances currently idle in this pool.
919      * @return count of instances available for checkout from the pool
920      */

921     public abstract int getNumIdle();
922
923     /**
924      * The listener used (if any) to receive notifications of exceptions
925      * unavoidably swallowed by the pool.
926      *
927      * @return The listener or <code>null</code> for no listener
928      */

929     public final SwallowedExceptionListener getSwallowedExceptionListener() {
930         return swallowedExceptionListener;
931     }
932
933     /**
934      * The listener used (if any) to receive notifications of exceptions
935      * unavoidably swallowed by the pool.
936      *
937      * @param swallowedExceptionListener    The listener or <code>null</code>
938      *                                      for no listener
939      */

940     public final void setSwallowedExceptionListener(
941             final SwallowedExceptionListener swallowedExceptionListener) {
942         this.swallowedExceptionListener = swallowedExceptionListener;
943     }
944
945     /**
946      * Swallows an exception and notifies the configured listener for swallowed
947      * exceptions queue.
948      *
949      * @param swallowException exception to be swallowed
950      */

951     final void swallowException(final Exception swallowException) {
952         final SwallowedExceptionListener listener = getSwallowedExceptionListener();
953
954         if (listener == null) {
955             return;
956         }
957
958         try {
959             listener.onSwallowException(swallowException);
960         } catch (final VirtualMachineError e) {
961             throw e;
962         } catch (final Throwable t) {
963             // Ignore. Enjoy the irony.
964         }
965     }
966
967     /**
968      * Updates statistics after an object is borrowed from the pool.
969      * @param p object borrowed from the pool
970      * @param waitTime time (in milliseconds) that the borrowing thread had to wait
971      */

972     final void updateStatsBorrow(final PooledObject<T> p, final long waitTime) {
973         borrowedCount.incrementAndGet();
974         idleTimes.add(p.getIdleTimeMillis());
975         waitTimes.add(waitTime);
976
977         // lock-free optimistic-locking maximum
978         long currentMax;
979         do {
980             currentMax = maxBorrowWaitTimeMillis.get();
981             if (currentMax >= waitTime) {
982                 break;
983             }
984         } while (!maxBorrowWaitTimeMillis.compareAndSet(currentMax, waitTime));
985     }
986
987     /**
988      * Updates statistics after an object is returned to the pool.
989      * @param activeTime the amount of time (in milliseconds) that the returning
990      * object was checked out
991      */

992     final void updateStatsReturn(final long activeTime) {
993         returnedCount.incrementAndGet();
994         activeTimes.add(activeTime);
995     }
996
997     /**
998      * Marks the object as returning to the pool.
999      * @param pooledObject instance to return to the keyed pool
1000      */

1001     protected void markReturningState(final PooledObject<T> pooledObject) {
1002         synchronized(pooledObject) {
1003             final PooledObjectState state = pooledObject.getState();
1004             if (state != PooledObjectState.ALLOCATED) {
1005                 throw new IllegalStateException(
1006                         "Object has already been returned to this pool or is invalid");
1007             }
1008             pooledObject.markReturning(); // Keep from being marked abandoned
1009         }
1010     }
1011
1012     /**
1013      * Unregisters this pool's MBean.
1014      */

1015     final void jmxUnregister() {
1016         if (objectName != null) {
1017             try {
1018                 ManagementFactory.getPlatformMBeanServer().unregisterMBean(
1019                         objectName);
1020             } catch (final MBeanRegistrationException | InstanceNotFoundException e) {
1021                 swallowException(e);
1022             }
1023         }
1024     }
1025
1026     /**
1027      * Registers the pool with the platform MBean server.
1028      * The registered name will be
1029      * <code>jmxNameBase + jmxNamePrefix + i</code> where i is the least
1030      * integer greater than or equal to 1 such that the name is not already
1031      * registered. Swallows MBeanRegistrationException, NotCompliantMBeanException
1032      * returning null.
1033      *
1034      * @param config Pool configuration
1035      * @param jmxNameBase default base JMX name for this pool
1036      * @param jmxNamePrefix name prefix
1037      * @return registered ObjectName, null if registration fails
1038      */

1039     private ObjectName jmxRegister(final BaseObjectPoolConfig<T> config,
1040             final String jmxNameBase, String jmxNamePrefix) {
1041         ObjectName newObjectName = null;
1042         final MBeanServer mbs = ManagementFactory.getPlatformMBeanServer();
1043         int i = 1;
1044         boolean registered = false;
1045         String base = config.getJmxNameBase();
1046         if (base == null) {
1047             base = jmxNameBase;
1048         }
1049         while (!registered) {
1050             try {
1051                 ObjectName objName;
1052                 // Skip the numeric suffix for the first pool in case there is
1053                 // only one so the names are cleaner.
1054                 if (i == 1) {
1055                     objName = new ObjectName(base + jmxNamePrefix);
1056                 } else {
1057                     objName = new ObjectName(base + jmxNamePrefix + i);
1058                 }
1059                 mbs.registerMBean(this, objName);
1060                 newObjectName = objName;
1061                 registered = true;
1062             } catch (final MalformedObjectNameException e) {
1063                 if (BaseObjectPoolConfig.DEFAULT_JMX_NAME_PREFIX.equals(
1064                         jmxNamePrefix) && jmxNameBase.equals(base)) {
1065                     // Shouldn't happen. Skip registration if it does.
1066                     registered = true;
1067                 } else {
1068                     // Must be an invalid name. Use the defaults instead.
1069                     jmxNamePrefix =
1070                             BaseObjectPoolConfig.DEFAULT_JMX_NAME_PREFIX;
1071                     base = jmxNameBase;
1072                 }
1073             } catch (final InstanceAlreadyExistsException e) {
1074                 // Increment the index and try again
1075                 i++;
1076             } catch (final MBeanRegistrationException | NotCompliantMBeanException e) {
1077                 // Shouldn't happen. Skip registration if it does.
1078                 registered = true;
1079             }
1080         }
1081         return newObjectName;
1082     }
1083
1084     /**
1085      * Gets the stack trace of an exception as a string.
1086      * @param e exception to trace
1087      * @return exception stack trace as a string
1088      */

1089     private String getStackTrace(final Exception e) {
1090         // Need the exception in string form to prevent the retention of
1091         // references to classes in the stack trace that could trigger a memory
1092         // leak in a container environment.
1093         final Writer w = new StringWriter();
1094         final PrintWriter pw = new PrintWriter(w);
1095         e.printStackTrace(pw);
1096         return w.toString();
1097     }
1098
1099     // Inner classes
1100
1101     /**
1102      * The idle object evictor {@link TimerTask}.
1103      *
1104      * @see GenericKeyedObjectPool#setTimeBetweenEvictionRunsMillis
1105      */

1106     class Evictor implements Runnable {
1107
1108         private ScheduledFuture<?> scheduledFuture;
1109
1110         /**
1111          * Run pool maintenance.  Evict objects qualifying for eviction and then
1112          * ensure that the minimum number of idle instances are available.
1113          * Since the Timer that invokes Evictors is shared for all Pools but
1114          * pools may exist in different class loaders, the Evictor ensures that
1115          * any actions taken are under the class loader of the factory
1116          * associated with the pool.
1117          */

1118         @Override
1119         public void run() {
1120             final ClassLoader savedClassLoader =
1121                     Thread.currentThread().getContextClassLoader();
1122             try {
1123                 if (factoryClassLoader != null) {
1124                     // Set the class loader for the factory
1125                     final ClassLoader cl = factoryClassLoader.get();
1126                     if (cl == null) {
1127                         // The pool has been dereferenced and the class loader
1128                         // GC'd. Cancel this timer so the pool can be GC'd as
1129                         // well.
1130                         cancel();
1131                         return;
1132                     }
1133                     Thread.currentThread().setContextClassLoader(cl);
1134                 }
1135
1136                 // Evict from the pool
1137                 try {
1138                     evict();
1139                 } catch(final Exception e) {
1140                     swallowException(e);
1141                 } catch(final OutOfMemoryError oome) {
1142                     // Log problem but give evictor thread a chance to continue
1143                     // in case error is recoverable
1144                     oome.printStackTrace(System.err);
1145                 }
1146                 // Re-create idle instances.
1147                 try {
1148                     ensureMinIdle();
1149                 } catch (final Exception e) {
1150                     swallowException(e);
1151                 }
1152             } finally {
1153                 // Restore the previous CCL
1154                 Thread.currentThread().setContextClassLoader(savedClassLoader);
1155             }
1156         }
1157
1158
1159         void setScheduledFuture(final ScheduledFuture<?> scheduledFuture) {
1160             this.scheduledFuture = scheduledFuture;
1161         }
1162
1163
1164         void cancel() {
1165             scheduledFuture.cancel(false);
1166         }
1167     }
1168
1169     /**
1170      * Maintains a cache of values for a single metric and reports
1171      * statistics on the cached values.
1172      */

1173     private class StatsStore {
1174
1175         private final AtomicLong values[];
1176         private final int size;
1177         private int index;
1178
1179         /**
1180          * Create a StatsStore with the given cache size.
1181          *
1182          * @param size number of values to maintain in the cache.
1183          */

1184         public StatsStore(final int size) {
1185             this.size = size;
1186             values = new AtomicLong[size];
1187             for (int i = 0; i < size; i++) {
1188                 values[i] = new AtomicLong(-1);
1189             }
1190         }
1191
1192         /**
1193          * Adds a value to the cache.  If the cache is full, one of the
1194          * existing values is replaced by the new value.
1195          *
1196          * @param value new value to add to the cache.
1197          */

1198         public synchronized void add(final long value) {
1199             values[index].set(value);
1200             index++;
1201             if (index == size) {
1202                 index = 0;
1203             }
1204         }
1205
1206         /**
1207          * Returns the mean of the cached values.
1208          *
1209          * @return the mean of the cache, truncated to long
1210          */

1211         public long getMean() {
1212             double result = 0;
1213             int counter = 0;
1214             for (int i = 0; i < size; i++) {
1215                 final long value = values[i].get();
1216                 if (value != -1) {
1217                     counter++;
1218                     result = result * ((counter - 1) / (double) counter) +
1219                             value/(double) counter;
1220                 }
1221             }
1222             return (long) result;
1223         }
1224
1225         @Override
1226         public String toString() {
1227             final StringBuilder builder = new StringBuilder();
1228             builder.append("StatsStore [values=");
1229             builder.append(Arrays.toString(values));
1230             builder.append(", size=");
1231             builder.append(size);
1232             builder.append(", index=");
1233             builder.append(index);
1234             builder.append("]");
1235             return builder.toString();
1236         }
1237     }
1238
1239     /**
1240      * The idle object eviction iterator. Holds a reference to the idle objects.
1241      */

1242     class EvictionIterator implements Iterator<PooledObject<T>> {
1243
1244         private final Deque<PooledObject<T>> idleObjects;
1245         private final Iterator<PooledObject<T>> idleObjectIterator;
1246
1247         /**
1248          * Create an EvictionIterator for the provided idle instance deque.
1249          * @param idleObjects underlying deque
1250          */

1251         EvictionIterator(final Deque<PooledObject<T>> idleObjects) {
1252             this.idleObjects = idleObjects;
1253
1254             if (getLifo()) {
1255                 idleObjectIterator = idleObjects.descendingIterator();
1256             } else {
1257                 idleObjectIterator = idleObjects.iterator();
1258             }
1259         }
1260
1261         /**
1262          * Returns the idle object deque referenced by this iterator.
1263          * @return the idle object deque
1264          */

1265         public Deque<PooledObject<T>> getIdleObjects() {
1266             return idleObjects;
1267         }
1268
1269         /** {@inheritDoc} */
1270         @Override
1271         public boolean hasNext() {
1272             return idleObjectIterator.hasNext();
1273         }
1274
1275         /** {@inheritDoc} */
1276         @Override
1277         public PooledObject<T> next() {
1278             return idleObjectIterator.next();
1279         }
1280
1281         /** {@inheritDoc} */
1282         @Override
1283         public void remove() {
1284             idleObjectIterator.remove();
1285         }
1286
1287     }
1288
1289     /**
1290      * Wrapper for objects under management by the pool.
1291      *
1292      * GenericObjectPool and GenericKeyedObjectPool maintain references to all
1293      * objects under management using maps keyed on the objects. This wrapper
1294      * class ensures that objects can work as hash keys.
1295      *
1296      * @param <T> type of objects in the pool
1297      */

1298     static class IdentityWrapper<T> {
1299         /** Wrapped object */
1300         private final T instance;
1301
1302         /**
1303          * Create a wrapper for an instance.
1304          *
1305          * @param instance object to wrap
1306          */

1307         public IdentityWrapper(final T instance) {
1308             this.instance = instance;
1309         }
1310
1311         @Override
1312         public int hashCode() {
1313             return System.identityHashCode(instance);
1314         }
1315
1316         @Override
1317         @SuppressWarnings("rawtypes")
1318         public boolean equals(final Object other) {
1319             return  other instanceof IdentityWrapper &&
1320                     ((IdentityWrapper) other).instance == instance;
1321         }
1322
1323         /**
1324          * @return the wrapped object
1325          */

1326         public T getObject() {
1327             return instance;
1328         }
1329
1330         @Override
1331         public String toString() {
1332             final StringBuilder builder = new StringBuilder();
1333             builder.append("IdentityWrapper [instance=");
1334             builder.append(instance);
1335             builder.append("]");
1336             return builder.toString();
1337         }
1338     }
1339
1340     @Override
1341     protected void toStringAppendFields(final StringBuilder builder) {
1342         builder.append("maxTotal=");
1343         builder.append(maxTotal);
1344         builder.append(", blockWhenExhausted=");
1345         builder.append(blockWhenExhausted);
1346         builder.append(", maxWaitMillis=");
1347         builder.append(maxWaitMillis);
1348         builder.append(", lifo=");
1349         builder.append(lifo);
1350         builder.append(", fairness=");
1351         builder.append(fairness);
1352         builder.append(", testOnCreate=");
1353         builder.append(testOnCreate);
1354         builder.append(", testOnBorrow=");
1355         builder.append(testOnBorrow);
1356         builder.append(", testOnReturn=");
1357         builder.append(testOnReturn);
1358         builder.append(", testWhileIdle=");
1359         builder.append(testWhileIdle);
1360         builder.append(", timeBetweenEvictionRunsMillis=");
1361         builder.append(timeBetweenEvictionRunsMillis);
1362         builder.append(", numTestsPerEvictionRun=");
1363         builder.append(numTestsPerEvictionRun);
1364         builder.append(", minEvictableIdleTimeMillis=");
1365         builder.append(minEvictableIdleTimeMillis);
1366         builder.append(", softMinEvictableIdleTimeMillis=");
1367         builder.append(softMinEvictableIdleTimeMillis);
1368         builder.append(", evictionPolicy=");
1369         builder.append(evictionPolicy);
1370         builder.append(", closeLock=");
1371         builder.append(closeLock);
1372         builder.append(", closed=");
1373         builder.append(closed);
1374         builder.append(", evictionLock=");
1375         builder.append(evictionLock);
1376         builder.append(", evictor=");
1377         builder.append(evictor);
1378         builder.append(", evictionIterator=");
1379         builder.append(evictionIterator);
1380         builder.append(", factoryClassLoader=");
1381         builder.append(factoryClassLoader);
1382         builder.append(", oname=");
1383         builder.append(objectName);
1384         builder.append(", creationStackTrace=");
1385         builder.append(creationStackTrace);
1386         builder.append(", borrowedCount=");
1387         builder.append(borrowedCount);
1388         builder.append(", returnedCount=");
1389         builder.append(returnedCount);
1390         builder.append(", createdCount=");
1391         builder.append(createdCount);
1392         builder.append(", destroyedCount=");
1393         builder.append(destroyedCount);
1394         builder.append(", destroyedByEvictorCount=");
1395         builder.append(destroyedByEvictorCount);
1396         builder.append(", destroyedByBorrowValidationCount=");
1397         builder.append(destroyedByBorrowValidationCount);
1398         builder.append(", activeTimes=");
1399         builder.append(activeTimes);
1400         builder.append(", idleTimes=");
1401         builder.append(idleTimes);
1402         builder.append(", waitTimes=");
1403         builder.append(waitTimes);
1404         builder.append(", maxBorrowWaitTimeMillis=");
1405         builder.append(maxBorrowWaitTimeMillis);
1406         builder.append(", swallowedExceptionListener=");
1407         builder.append(swallowedExceptionListener);
1408     }
1409
1410
1411 }
1412