001/*
002 * Licensed to the Apache Software Foundation (ASF) under one or more
003 * contributor license agreements.  See the NOTICE file distributed with
004 * this work for additional information regarding copyright ownership.
005 * The ASF licenses this file to You under the Apache License, Version 2.0
006 * (the "License"); you may not use this file except in compliance with
007 * the License.  You may obtain a copy of the License at
008 *
009 *      http://www.apache.org/licenses/LICENSE-2.0
010 *
011 * Unless required by applicable law or agreed to in writing, software
012 * distributed under the License is distributed on an "AS IS" BASIS,
013 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
014 * See the License for the specific language governing permissions and
015 * limitations under the License.
016 */
017package org.apache.commons.pool2.impl;
018
019import java.io.PrintWriter;
020import java.io.StringWriter;
021import java.io.Writer;
022import java.lang.management.ManagementFactory;
023import java.lang.ref.WeakReference;
024import java.lang.reflect.InvocationTargetException;
025import java.util.Arrays;
026import java.util.Deque;
027import java.util.Iterator;
028import java.util.TimerTask;
029import java.util.concurrent.ScheduledFuture;
030import java.util.concurrent.TimeUnit;
031import java.util.concurrent.atomic.AtomicLong;
032
033import javax.management.InstanceAlreadyExistsException;
034import javax.management.InstanceNotFoundException;
035import javax.management.MBeanRegistrationException;
036import javax.management.MBeanServer;
037import javax.management.MalformedObjectNameException;
038import javax.management.NotCompliantMBeanException;
039import javax.management.ObjectName;
040
041import org.apache.commons.pool2.BaseObject;
042import org.apache.commons.pool2.PooledObject;
043import org.apache.commons.pool2.PooledObjectState;
044import org.apache.commons.pool2.SwallowedExceptionListener;
045
046/**
047 * Base class that provides common functionality for {@link GenericObjectPool}
048 * and {@link GenericKeyedObjectPool}. The primary reason this class exists is
049 * reduce code duplication between the two pool implementations.
050 *
051 * @param <T> Type of element pooled in this pool.
052 *
053 * This class is intended to be thread-safe.
054 *
055 * @since 2.0
056 */
057public abstract class BaseGenericObjectPool<T> extends BaseObject {
058
059    // Constants
060    /**
061     * The size of the caches used to store historical data for some attributes
062     * so that rolling means may be calculated.
063     */
064    public static final int MEAN_TIMING_STATS_CACHE_SIZE = 100;
065
066    private static final String EVICTION_POLICY_TYPE_NAME = EvictionPolicy.class.getName();
067
068    // Configuration attributes
069    private volatile int maxTotal =
070            GenericKeyedObjectPoolConfig.DEFAULT_MAX_TOTAL;
071    private volatile boolean blockWhenExhausted =
072            BaseObjectPoolConfig.DEFAULT_BLOCK_WHEN_EXHAUSTED;
073    private volatile long maxWaitMillis =
074            BaseObjectPoolConfig.DEFAULT_MAX_WAIT_MILLIS;
075    private volatile boolean lifo = BaseObjectPoolConfig.DEFAULT_LIFO;
076    private final boolean fairness;
077    private volatile boolean testOnCreate =
078            BaseObjectPoolConfig.DEFAULT_TEST_ON_CREATE;
079    private volatile boolean testOnBorrow =
080            BaseObjectPoolConfig.DEFAULT_TEST_ON_BORROW;
081    private volatile boolean testOnReturn =
082            BaseObjectPoolConfig.DEFAULT_TEST_ON_RETURN;
083    private volatile boolean testWhileIdle =
084            BaseObjectPoolConfig.DEFAULT_TEST_WHILE_IDLE;
085    private volatile long timeBetweenEvictionRunsMillis =
086            BaseObjectPoolConfig.DEFAULT_TIME_BETWEEN_EVICTION_RUNS_MILLIS;
087    private volatile int numTestsPerEvictionRun =
088            BaseObjectPoolConfig.DEFAULT_NUM_TESTS_PER_EVICTION_RUN;
089    private volatile long minEvictableIdleTimeMillis =
090            BaseObjectPoolConfig.DEFAULT_MIN_EVICTABLE_IDLE_TIME_MILLIS;
091    private volatile long softMinEvictableIdleTimeMillis =
092            BaseObjectPoolConfig.DEFAULT_SOFT_MIN_EVICTABLE_IDLE_TIME_MILLIS;
093    private volatile EvictionPolicy<T> evictionPolicy;
094    private volatile long evictorShutdownTimeoutMillis =
095            BaseObjectPoolConfig.DEFAULT_EVICTOR_SHUTDOWN_TIMEOUT_MILLIS;
096
097
098    // Internal (primarily state) attributes
099    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()} method is
193     * invoked when the pool is exhausted (the maximum number of "active"
194     * objects has been reached).
195     *
196     * @return {@code true} if {@code borrowObject()} 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()} 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} if
211     *                              {@code borrowObject()} 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    /**
221     * Initializes the receiver with the given configuration.
222     *
223     * @param config Initialization source.
224     */
225    protected void setConfig(final BaseObjectPoolConfig<T> config) {
226        setLifo(config.getLifo());
227        setMaxWaitMillis(config.getMaxWaitMillis());
228        setBlockWhenExhausted(config.getBlockWhenExhausted());
229        setTestOnCreate(config.getTestOnCreate());
230        setTestOnBorrow(config.getTestOnBorrow());
231        setTestOnReturn(config.getTestOnReturn());
232        setTestWhileIdle(config.getTestWhileIdle());
233        setNumTestsPerEvictionRun(config.getNumTestsPerEvictionRun());
234        setMinEvictableIdleTimeMillis(config.getMinEvictableIdleTimeMillis());
235        setTimeBetweenEvictionRunsMillis(config.getTimeBetweenEvictionRunsMillis());
236        setSoftMinEvictableIdleTimeMillis(config.getSoftMinEvictableIdleTimeMillis());
237        final EvictionPolicy<T> policy = config.getEvictionPolicy();
238        if (policy == null) {
239            // Use the class name (pre-2.6.0 compatible)
240            setEvictionPolicyClassName(config.getEvictionPolicyClassName());
241        } else {
242            // Otherwise, use the class (2.6.0 feature)
243            setEvictionPolicy(policy);
244        }
245        setEvictorShutdownTimeoutMillis(config.getEvictorShutdownTimeoutMillis());
246    }
247
248    /**
249     * Returns the maximum amount of time (in milliseconds) the
250     * {@code borrowObject()} method should block before throwing an
251     * exception when the pool is exhausted and
252     * {@link #getBlockWhenExhausted} is true. When less than 0, the
253     * {@code borrowObject()} method may block indefinitely.
254     *
255     * @return the maximum number of milliseconds {@code borrowObject()}
256     *         will block.
257     *
258     * @see #setMaxWaitMillis
259     * @see #setBlockWhenExhausted
260     */
261    public final long getMaxWaitMillis() {
262        return maxWaitMillis;
263    }
264
265    /**
266     * Sets the maximum amount of time (in milliseconds) the
267     * {@code borrowObject()} method should block before throwing an
268     * exception when the pool is exhausted and
269     * {@link #getBlockWhenExhausted} is true. When less than 0, the
270     * {@code borrowObject()} method may block indefinitely.
271     *
272     * @param maxWaitMillis the maximum number of milliseconds
273     *                      {@code borrowObject()} will block or negative
274     *                      for indefinitely.
275     *
276     * @see #getMaxWaitMillis
277     * @see #setBlockWhenExhausted
278     */
279    public final void setMaxWaitMillis(final long maxWaitMillis) {
280        this.maxWaitMillis = maxWaitMillis;
281    }
282
283    /**
284     * Returns whether the pool has LIFO (last in, first out) behavior with
285     * respect to idle objects - always returning the most recently used object
286     * from the pool, or as a FIFO (first in, first out) queue, where the pool
287     * always returns the oldest object in the idle object pool.
288     *
289     * @return {@code true} if the pool is configured with LIFO behavior
290     *         or {@code false} if the pool is configured with FIFO
291     *         behavior
292     *
293     * @see #setLifo
294     */
295    public final boolean getLifo() {
296        return lifo;
297    }
298
299    /**
300     * Returns whether or not the pool serves threads waiting to borrow objects fairly.
301     * True means that waiting threads are served as if waiting in a FIFO queue.
302     *
303     * @return {@code true} if waiting threads are to be served
304     *             by the pool in arrival order
305     */
306    public final boolean getFairness() {
307        return fairness;
308    }
309
310    /**
311     * Sets whether the pool has LIFO (last in, first out) behavior with
312     * respect to idle objects - always returning the most recently used object
313     * from the pool, or as a FIFO (first in, first out) queue, where the pool
314     * always returns the oldest object in the idle object pool.
315     *
316     * @param lifo  {@code true} if the pool is to be configured with LIFO
317     *              behavior or {@code false} if the pool is to be
318     *              configured with FIFO behavior
319     *
320     * @see #getLifo()
321     */
322    public final void setLifo(final boolean lifo) {
323        this.lifo = lifo;
324    }
325
326    /**
327     * Returns whether objects created for the pool will be validated before
328     * being returned from the {@code borrowObject()} method. Validation is
329     * performed by the {@code validateObject()} method of the factory
330     * associated with the pool. If the object fails to validate, then
331     * {@code borrowObject()} will fail.
332     *
333     * @return {@code true} if newly created objects are validated before
334     *         being returned from the {@code borrowObject()} method
335     *
336     * @see #setTestOnCreate
337     *
338     * @since 2.2
339     */
340    public final boolean getTestOnCreate() {
341        return testOnCreate;
342    }
343
344    /**
345     * Sets whether objects created for the pool will be validated before
346     * being returned from the {@code borrowObject()} method. Validation is
347     * performed by the {@code validateObject()} method of the factory
348     * associated with the pool. If the object fails to validate, then
349     * {@code borrowObject()} will fail.
350     *
351     * @param testOnCreate  {@code true} if newly created objects should be
352     *                      validated before being returned from the
353     *                      {@code borrowObject()} method
354     *
355     * @see #getTestOnCreate
356     *
357     * @since 2.2
358     */
359    public final void setTestOnCreate(final boolean testOnCreate) {
360        this.testOnCreate = testOnCreate;
361    }
362
363    /**
364     * Returns whether objects borrowed from the pool will be validated before
365     * being returned from the {@code borrowObject()} method. Validation is
366     * performed by the {@code validateObject()} method of the factory
367     * associated with the pool. If the object fails to validate, it will be
368     * removed from the pool and destroyed, and a new attempt will be made to
369     * borrow an object from the pool.
370     *
371     * @return {@code true} if objects are validated before being returned
372     *         from the {@code borrowObject()} method
373     *
374     * @see #setTestOnBorrow
375     */
376    public final boolean getTestOnBorrow() {
377        return testOnBorrow;
378    }
379
380    /**
381     * Sets whether objects borrowed from the pool will be validated before
382     * being returned from the {@code borrowObject()} method. Validation is
383     * performed by the {@code validateObject()} method of the factory
384     * associated with the pool. If the object fails to validate, it will be
385     * removed from the pool and destroyed, and a new attempt will be made to
386     * borrow an object from the pool.
387     *
388     * @param testOnBorrow  {@code true} if objects should be validated
389     *                      before being returned from the
390     *                      {@code borrowObject()} method
391     *
392     * @see #getTestOnBorrow
393     */
394    public final void setTestOnBorrow(final boolean testOnBorrow) {
395        this.testOnBorrow = testOnBorrow;
396    }
397
398    /**
399     * Returns whether objects borrowed from the pool will be validated when
400     * they are returned to the pool via the {@code returnObject()} method.
401     * Validation is performed by the {@code validateObject()} method of
402     * the factory associated with the pool. Returning objects that fail validation
403     * are destroyed rather then being returned the pool.
404     *
405     * @return {@code true} if objects are validated on return to
406     *         the pool via the {@code returnObject()} method
407     *
408     * @see #setTestOnReturn
409     */
410    public final boolean getTestOnReturn() {
411        return testOnReturn;
412    }
413
414    /**
415     * Sets whether objects borrowed from the pool will be validated when
416     * they are returned to the pool via the {@code returnObject()} method.
417     * Validation is performed by the {@code validateObject()} method of
418     * the factory associated with the pool. Returning objects that fail validation
419     * are destroyed rather then being returned the pool.
420     *
421     * @param testOnReturn {@code true} if objects are validated on
422     *                     return to the pool via the
423     *                     {@code returnObject()} method
424     *
425     * @see #getTestOnReturn
426     */
427    public final void setTestOnReturn(final boolean testOnReturn) {
428        this.testOnReturn = testOnReturn;
429    }
430
431    /**
432     * Returns whether objects sitting idle in the pool will be validated by the
433     * idle object evictor (if any - see
434     * {@link #setTimeBetweenEvictionRunsMillis(long)}). Validation is performed
435     * by the {@code validateObject()} method of the factory associated
436     * with the pool. If the object fails to validate, it will be removed from
437     * the pool and destroyed.
438     *
439     * @return {@code true} if objects will be validated by the evictor
440     *
441     * @see #setTestWhileIdle
442     * @see #setTimeBetweenEvictionRunsMillis
443     */
444    public final boolean getTestWhileIdle() {
445        return testWhileIdle;
446    }
447
448    /**
449     * Returns whether objects sitting idle in the pool will be validated by the
450     * idle object evictor (if any - see
451     * {@link #setTimeBetweenEvictionRunsMillis(long)}). Validation is performed
452     * by the {@code validateObject()} method of the factory associated
453     * with the pool. If the object fails to validate, it will be removed from
454     * the pool and destroyed.  Note that setting this property has no effect
455     * unless the idle object evictor is enabled by setting
456     * {@code timeBetweenEvictionRunsMillis} to a positive value.
457     *
458     * @param testWhileIdle
459     *            {@code true} so objects will be validated by the evictor
460     *
461     * @see #getTestWhileIdle
462     * @see #setTimeBetweenEvictionRunsMillis
463     */
464    public final void setTestWhileIdle(final boolean testWhileIdle) {
465        this.testWhileIdle = testWhileIdle;
466    }
467
468    /**
469     * Returns the number of milliseconds to sleep between runs of the idle
470     * object evictor thread. When non-positive, no idle object evictor thread
471     * will be run.
472     *
473     * @return number of milliseconds to sleep between evictor runs
474     *
475     * @see #setTimeBetweenEvictionRunsMillis
476     */
477    public final long getTimeBetweenEvictionRunsMillis() {
478        return timeBetweenEvictionRunsMillis;
479    }
480
481    /**
482     * Sets the number of milliseconds to sleep between runs of the idle object evictor thread.
483     * <ul>
484     * <li>When positive, the idle object evictor thread starts.</li>
485     * <li>When non-positive, no idle object evictor thread runs.</li>
486     * </ul>
487     *
488     * @param timeBetweenEvictionRunsMillis
489     *            number of milliseconds to sleep between evictor runs
490     *
491     * @see #getTimeBetweenEvictionRunsMillis
492     */
493    public final void setTimeBetweenEvictionRunsMillis(
494            final long timeBetweenEvictionRunsMillis) {
495        this.timeBetweenEvictionRunsMillis = timeBetweenEvictionRunsMillis;
496        startEvictor(timeBetweenEvictionRunsMillis);
497    }
498
499    /**
500     * Returns the maximum number of objects to examine during each run (if any)
501     * of the idle object evictor thread. When positive, the number of tests
502     * performed for a run will be the minimum of the configured value and the
503     * number of idle instances in the pool. When negative, the number of tests
504     * performed will be <code>ceil({@link #getNumIdle}/
505     * abs({@link #getNumTestsPerEvictionRun}))</code> which means that when the
506     * value is {@code -n} roughly one nth of the idle objects will be
507     * tested per run.
508     *
509     * @return max number of objects to examine during each evictor run
510     *
511     * @see #setNumTestsPerEvictionRun
512     * @see #setTimeBetweenEvictionRunsMillis
513     */
514    public final int getNumTestsPerEvictionRun() {
515        return numTestsPerEvictionRun;
516    }
517
518    /**
519     * Sets the maximum number of objects to examine during each run (if any)
520     * of the idle object evictor thread. When positive, the number of tests
521     * performed for a run will be the minimum of the configured value and the
522     * number of idle instances in the pool. When negative, the number of tests
523     * performed will be <code>ceil({@link #getNumIdle}/
524     * abs({@link #getNumTestsPerEvictionRun}))</code> which means that when the
525     * value is {@code -n} roughly one nth of the idle objects will be
526     * tested per run.
527     *
528     * @param numTestsPerEvictionRun
529     *            max number of objects to examine during each evictor run
530     *
531     * @see #getNumTestsPerEvictionRun
532     * @see #setTimeBetweenEvictionRunsMillis
533     */
534    public final void setNumTestsPerEvictionRun(final int numTestsPerEvictionRun) {
535        this.numTestsPerEvictionRun = numTestsPerEvictionRun;
536    }
537
538    /**
539     * Returns the minimum amount of time an object may sit idle in the pool
540     * before it is eligible for eviction by the idle object evictor (if any -
541     * see {@link #setTimeBetweenEvictionRunsMillis(long)}). When non-positive,
542     * no objects will be evicted from the pool due to idle time alone.
543     *
544     * @return minimum amount of time an object may sit idle in the pool before
545     *         it is eligible for eviction
546     *
547     * @see #setMinEvictableIdleTimeMillis
548     * @see #setTimeBetweenEvictionRunsMillis
549     */
550    public final long getMinEvictableIdleTimeMillis() {
551        return minEvictableIdleTimeMillis;
552    }
553
554    /**
555     * Sets the minimum amount of time an object may sit idle in the pool
556     * before it is eligible for eviction by the idle object evictor (if any -
557     * see {@link #setTimeBetweenEvictionRunsMillis(long)}). When non-positive,
558     * no objects will be evicted from the pool due to idle time alone.
559     *
560     * @param minEvictableIdleTimeMillis
561     *            minimum amount of time an object may sit idle in the pool
562     *            before it is eligible for eviction
563     *
564     * @see #getMinEvictableIdleTimeMillis
565     * @see #setTimeBetweenEvictionRunsMillis
566     */
567    public final void setMinEvictableIdleTimeMillis(
568            final long minEvictableIdleTimeMillis) {
569        this.minEvictableIdleTimeMillis = minEvictableIdleTimeMillis;
570    }
571
572    /**
573     * Returns the minimum amount of time an object may sit idle in the pool
574     * before it is eligible for eviction by the idle object evictor (if any -
575     * see {@link #setTimeBetweenEvictionRunsMillis(long)}),
576     * with the extra condition that at least {@code minIdle} object
577     * instances remain in the pool. This setting is overridden by
578     * {@link #getMinEvictableIdleTimeMillis} (that is, if
579     * {@link #getMinEvictableIdleTimeMillis} is positive, then
580     * {@link #getSoftMinEvictableIdleTimeMillis} is ignored).
581     *
582     * @return minimum amount of time an object may sit idle in the pool before
583     *         it is eligible for eviction if minIdle instances are available
584     *
585     * @see #setSoftMinEvictableIdleTimeMillis
586     */
587    public final long getSoftMinEvictableIdleTimeMillis() {
588        return softMinEvictableIdleTimeMillis;
589    }
590
591    /**
592     * Sets the minimum amount of time an object may sit idle in the pool
593     * before it is eligible for eviction by the idle object evictor (if any -
594     * see {@link #setTimeBetweenEvictionRunsMillis(long)}),
595     * with the extra condition that at least {@code minIdle} object
596     * instances remain in the pool. This setting is overridden by
597     * {@link #getMinEvictableIdleTimeMillis} (that is, if
598     * {@link #getMinEvictableIdleTimeMillis} is positive, then
599     * {@link #getSoftMinEvictableIdleTimeMillis} is ignored).
600     *
601     * @param softMinEvictableIdleTimeMillis
602     *            minimum amount of time an object may sit idle in the pool
603     *            before it is eligible for eviction if minIdle instances are
604     *            available
605     *
606     * @see #getSoftMinEvictableIdleTimeMillis
607     */
608    public final void setSoftMinEvictableIdleTimeMillis(
609            final long softMinEvictableIdleTimeMillis) {
610        this.softMinEvictableIdleTimeMillis = softMinEvictableIdleTimeMillis;
611    }
612
613    /**
614     * Returns the name of the {@link EvictionPolicy} implementation that is
615     * used by this pool.
616     *
617     * @return  The fully qualified class name of the {@link EvictionPolicy}
618     *
619     * @see #setEvictionPolicyClassName(String)
620     */
621    public final String getEvictionPolicyClassName() {
622        return evictionPolicy.getClass().getName();
623    }
624
625    /**
626     * Sets the eviction policy for this pool.
627     *
628     * @param evictionPolicy
629     *            the eviction policy for this pool.
630     * @since 2.6.0
631     */
632    public void setEvictionPolicy(final EvictionPolicy<T> evictionPolicy) {
633        this.evictionPolicy = evictionPolicy;
634    }
635
636    /**
637     * Sets the name of the {@link EvictionPolicy} implementation that is used by this pool. The Pool will attempt to
638     * load the class using the given class loader. If that fails, use the class loader for the {@link EvictionPolicy}
639     * interface.
640     *
641     * @param evictionPolicyClassName
642     *            the fully qualified class name of the new eviction policy
643     * @param classLoader
644     *            the class loader to load the given {@code evictionPolicyClassName}.
645     *
646     * @see #getEvictionPolicyClassName()
647     * @since 2.6.0 If loading the class using the given class loader fails, use the class loader for the
648     *        {@link EvictionPolicy} interface.
649     */
650    public final void setEvictionPolicyClassName(final String evictionPolicyClassName, final ClassLoader classLoader) {
651        // Getting epClass here and now best matches the caller's environment
652        final Class<?> epClass = EvictionPolicy.class;
653        final ClassLoader epClassLoader = epClass.getClassLoader();
654        try {
655            try {
656                setEvictionPolicy(evictionPolicyClassName, classLoader);
657            } catch (final ClassCastException | ClassNotFoundException e) {
658                setEvictionPolicy(evictionPolicyClassName, epClassLoader);
659            }
660        } catch (final ClassCastException e) {
661            throw new IllegalArgumentException("Class " + evictionPolicyClassName + " from class loaders [" +
662                    classLoader + ", " + epClassLoader + "] do not implement " + EVICTION_POLICY_TYPE_NAME);
663        } catch (final ClassNotFoundException | InstantiationException | IllegalAccessException |
664                InvocationTargetException | NoSuchMethodException e) {
665            final String exMessage = "Unable to create " + EVICTION_POLICY_TYPE_NAME + " instance of type " +
666                    evictionPolicyClassName;
667            throw new IllegalArgumentException(exMessage, e);
668        }
669    }
670
671    /**
672     * Sets the eviction policy.
673     *
674     * @param className Eviction policy class name.
675     * @param classLoader Load the class from this class loader.
676     */
677    @SuppressWarnings("unchecked")
678    private void setEvictionPolicy(final String className, final ClassLoader classLoader)
679            throws ClassNotFoundException, InstantiationException, IllegalAccessException, InvocationTargetException, NoSuchMethodException {
680        final Class<?> clazz = Class.forName(className, true, classLoader);
681        final Object policy = clazz.getConstructor().newInstance();
682        this.evictionPolicy = (EvictionPolicy<T>) policy;
683    }
684
685    /**
686     * Sets the name of the {@link EvictionPolicy} implementation that is used by this pool. The Pool will attempt to
687     * load the class using the thread context class loader. If that fails, the use the class loader for the
688     * {@link EvictionPolicy} interface.
689     *
690     * @param evictionPolicyClassName
691     *            the fully qualified class name of the new eviction policy
692     *
693     * @see #getEvictionPolicyClassName()
694     * @since 2.6.0 If loading the class using the thread context class loader fails, use the class loader for the
695     *        {@link EvictionPolicy} interface.
696     */
697    public final void setEvictionPolicyClassName(final String evictionPolicyClassName) {
698        setEvictionPolicyClassName(evictionPolicyClassName, Thread.currentThread().getContextClassLoader());
699    }
700
701    /**
702     * Gets the timeout that will be used when waiting for the Evictor to
703     * shutdown if this pool is closed and it is the only pool still using the
704     * the value for the Evictor.
705     *
706     * @return  The timeout in milliseconds that will be used while waiting for
707     *          the Evictor to shut down.
708     */
709    public final long getEvictorShutdownTimeoutMillis() {
710        return evictorShutdownTimeoutMillis;
711    }
712
713    /**
714     * Sets the timeout that will be used when waiting for the Evictor to
715     * shutdown if this pool is closed and it is the only pool still using the
716     * the value for the Evictor.
717     *
718     * @param evictorShutdownTimeoutMillis  the timeout in milliseconds that
719     *                                      will be used while waiting for the
720     *                                      Evictor to shut down.
721     */
722    public final void setEvictorShutdownTimeoutMillis(
723            final long evictorShutdownTimeoutMillis) {
724        this.evictorShutdownTimeoutMillis = evictorShutdownTimeoutMillis;
725    }
726
727    /**
728     * Closes the pool, destroys the remaining idle objects and, if registered
729     * in JMX, deregisters it.
730     */
731    public abstract void close();
732
733    /**
734     * Has this pool instance been closed.
735     * @return {@code true} when this pool has been closed.
736     */
737    public final boolean isClosed() {
738        return closed;
739    }
740
741    /**
742     * <p>Perform {@code numTests} idle object eviction tests, evicting
743     * examined objects that meet the criteria for eviction. If
744     * {@code testWhileIdle} is true, examined objects are validated
745     * when visited (and removed if invalid); otherwise only objects that
746     * have been idle for more than {@code minEvicableIdleTimeMillis}
747     * are removed.</p>
748     *
749     * @throws Exception when there is a problem evicting idle objects.
750     */
751    public abstract void evict() throws Exception;
752
753    /**
754     * Returns the {@link EvictionPolicy} defined for this pool.
755     *
756     * @return the eviction policy
757     * @since 2.4
758     * @since 2.6.0 Changed access from protected to public.
759     */
760    public EvictionPolicy<T> getEvictionPolicy() {
761        return evictionPolicy;
762    }
763
764    /**
765     * Verifies that the pool is open.
766     * @throws IllegalStateException if the pool is closed.
767     */
768    final void assertOpen() throws IllegalStateException {
769        if (isClosed()) {
770            throw new IllegalStateException("Pool not open");
771        }
772    }
773
774    /**
775     * <p>Starts the evictor with the given delay. If there is an evictor
776     * running when this method is called, it is stopped and replaced with a
777     * new evictor with the specified delay.</p>
778     *
779     * <p>This method needs to be final, since it is called from a constructor.
780     * See POOL-195.</p>
781     *
782     * @param delay time in milliseconds before start and between eviction runs
783     */
784    final void startEvictor(final long delay) {
785        synchronized (evictionLock) {
786            if (evictor == null) { // Starting evictor for the first time or after a cancel
787                if (delay > 0) {   // Starting new evictor
788                    evictor = new Evictor();
789                    EvictionTimer.schedule(evictor, delay, delay);
790                }
791            } else {  // Stop or restart of existing evictor
792                if (delay > 0) { // Restart
793                    synchronized (EvictionTimer.class) { // Ensure no cancel can happen between cancel / schedule calls
794                        EvictionTimer.cancel(evictor, evictorShutdownTimeoutMillis, TimeUnit.MILLISECONDS, true);
795                        evictor = null;
796                        evictionIterator = null;
797                        evictor = new Evictor();
798                        EvictionTimer.schedule(evictor, delay, delay);
799                    }
800                } else { // Stopping evictor
801                    EvictionTimer.cancel(evictor, evictorShutdownTimeoutMillis, TimeUnit.MILLISECONDS, false);
802                }
803            }
804        }
805    }
806
807    /**
808     * Stops the evictor.
809     */
810    void stopEvictor() {
811        startEvictor(-1L);
812    }
813    /**
814     * Tries to ensure that the configured minimum number of idle instances are
815     * available in the pool.
816     * @throws Exception if an error occurs creating idle instances
817     */
818    abstract void ensureMinIdle() throws Exception;
819
820
821    // Monitoring (primarily JMX) related methods
822
823    /**
824     * Provides the name under which the pool has been registered with the
825     * platform MBean server or {@code null} if the pool has not been
826     * registered.
827     * @return the JMX name
828     */
829    public final ObjectName getJmxName() {
830        return objectName;
831    }
832
833    /**
834     * Provides the stack trace for the call that created this pool. JMX
835     * registration may trigger a memory leak so it is important that pools are
836     * deregistered when no longer used by calling the {@link #close()} method.
837     * This method is provided to assist with identifying code that creates but
838     * does not close it thereby creating a memory leak.
839     * @return pool creation stack trace
840     */
841    public final String getCreationStackTrace() {
842        return creationStackTrace;
843    }
844
845    /**
846     * The total number of objects successfully borrowed from this pool over the
847     * lifetime of the pool.
848     * @return the borrowed object count
849     */
850    public final long getBorrowedCount() {
851        return borrowedCount.get();
852    }
853
854    /**
855     * The total number of objects returned to this pool over the lifetime of
856     * the pool. This excludes attempts to return the same object multiple
857     * times.
858     * @return the returned object count
859     */
860    public final long getReturnedCount() {
861        return returnedCount.get();
862    }
863
864    /**
865     * The total number of objects created for this pool over the lifetime of
866     * the pool.
867     * @return the created object count
868     */
869    public final long getCreatedCount() {
870        return createdCount.get();
871    }
872
873    /**
874     * The total number of objects destroyed by this pool over the lifetime of
875     * the pool.
876     * @return the destroyed object count
877     */
878    public final long getDestroyedCount() {
879        return destroyedCount.get();
880    }
881
882    /**
883     * The total number of objects destroyed by the evictor associated with this
884     * pool over the lifetime of the pool.
885     * @return the evictor destroyed object count
886     */
887    public final long getDestroyedByEvictorCount() {
888        return destroyedByEvictorCount.get();
889    }
890
891    /**
892     * The total number of objects destroyed by this pool as a result of failing
893     * validation during {@code borrowObject()} over the lifetime of the
894     * pool.
895     * @return validation destroyed object count
896     */
897    public final long getDestroyedByBorrowValidationCount() {
898        return destroyedByBorrowValidationCount.get();
899    }
900
901    /**
902     * The mean time objects are active for based on the last {@link
903     * #MEAN_TIMING_STATS_CACHE_SIZE} objects returned to the pool.
904     * @return mean time an object has been checked out from the pool among
905     * recently returned objects
906     */
907    public final long getMeanActiveTimeMillis() {
908        return activeTimes.getMean();
909    }
910
911    /**
912     * The mean time objects are idle for based on the last {@link
913     * #MEAN_TIMING_STATS_CACHE_SIZE} objects borrowed from the pool.
914     * @return mean time an object has been idle in the pool among recently
915     * borrowed objects
916     */
917    public final long getMeanIdleTimeMillis() {
918        return idleTimes.getMean();
919    }
920
921    /**
922     * The mean time threads wait to borrow an object based on the last {@link
923     * #MEAN_TIMING_STATS_CACHE_SIZE} objects borrowed from the pool.
924     * @return mean time in milliseconds that a recently served thread has had
925     * to wait to borrow an object from the pool
926     */
927    public final long getMeanBorrowWaitTimeMillis() {
928        return waitTimes.getMean();
929    }
930
931    /**
932     * The maximum time a thread has waited to borrow objects from the pool.
933     * @return maximum wait time in milliseconds since the pool was created
934     */
935    public final long getMaxBorrowWaitTimeMillis() {
936        return maxBorrowWaitTimeMillis.get();
937    }
938
939    /**
940     * The number of instances currently idle in this pool.
941     * @return count of instances available for checkout from the pool
942     */
943    public abstract int getNumIdle();
944
945    /**
946     * The listener used (if any) to receive notifications of exceptions
947     * unavoidably swallowed by the pool.
948     *
949     * @return The listener or {@code null} for no listener
950     */
951    public final SwallowedExceptionListener getSwallowedExceptionListener() {
952        return swallowedExceptionListener;
953    }
954
955    /**
956     * The listener used (if any) to receive notifications of exceptions
957     * unavoidably swallowed by the pool.
958     *
959     * @param swallowedExceptionListener    The listener or {@code null}
960     *                                      for no listener
961     */
962    public final void setSwallowedExceptionListener(
963            final SwallowedExceptionListener swallowedExceptionListener) {
964        this.swallowedExceptionListener = swallowedExceptionListener;
965    }
966
967    /**
968     * Swallows an exception and notifies the configured listener for swallowed
969     * exceptions queue.
970     *
971     * @param swallowException exception to be swallowed
972     */
973    final void swallowException(final Exception swallowException) {
974        final SwallowedExceptionListener listener = getSwallowedExceptionListener();
975
976        if (listener == null) {
977            return;
978        }
979
980        try {
981            listener.onSwallowException(swallowException);
982        } catch (final VirtualMachineError e) {
983            throw e;
984        } catch (final Throwable t) {
985            // Ignore. Enjoy the irony.
986        }
987    }
988
989    /**
990     * Updates statistics after an object is borrowed from the pool.
991     * @param p object borrowed from the pool
992     * @param waitTime time (in milliseconds) that the borrowing thread had to wait
993     */
994    final void updateStatsBorrow(final PooledObject<T> p, final long waitTime) {
995        borrowedCount.incrementAndGet();
996        idleTimes.add(p.getIdleTimeMillis());
997        waitTimes.add(waitTime);
998
999        // lock-free optimistic-locking maximum
1000        long currentMax;
1001        do {
1002            currentMax = maxBorrowWaitTimeMillis.get();
1003            if (currentMax >= waitTime) {
1004                break;
1005            }
1006        } while (!maxBorrowWaitTimeMillis.compareAndSet(currentMax, waitTime));
1007    }
1008
1009    /**
1010     * Updates statistics after an object is returned to the pool.
1011     * @param activeTime the amount of time (in milliseconds) that the returning
1012     * object was checked out
1013     */
1014    final void updateStatsReturn(final long activeTime) {
1015        returnedCount.incrementAndGet();
1016        activeTimes.add(activeTime);
1017    }
1018
1019    /**
1020     * Marks the object as returning to the pool.
1021     * @param pooledObject instance to return to the keyed pool
1022     */
1023    protected void markReturningState(final PooledObject<T> pooledObject) {
1024        synchronized(pooledObject) {
1025            final PooledObjectState state = pooledObject.getState();
1026            if (state != PooledObjectState.ALLOCATED) {
1027                throw new IllegalStateException(
1028                        "Object has already been returned to this pool or is invalid");
1029            }
1030            pooledObject.markReturning(); // Keep from being marked abandoned
1031        }
1032    }
1033
1034    /**
1035     * Unregisters this pool's MBean.
1036     */
1037    final void jmxUnregister() {
1038        if (objectName != null) {
1039            try {
1040                ManagementFactory.getPlatformMBeanServer().unregisterMBean(
1041                        objectName);
1042            } catch (final MBeanRegistrationException | InstanceNotFoundException e) {
1043                swallowException(e);
1044            }
1045        }
1046    }
1047
1048    /**
1049     * Registers the pool with the platform MBean server.
1050     * The registered name will be
1051     * {@code jmxNameBase + jmxNamePrefix + i} where i is the least
1052     * integer greater than or equal to 1 such that the name is not already
1053     * registered. Swallows MBeanRegistrationException, NotCompliantMBeanException
1054     * returning null.
1055     *
1056     * @param config Pool configuration
1057     * @param jmxNameBase default base JMX name for this pool
1058     * @param jmxNamePrefix name prefix
1059     * @return registered ObjectName, null if registration fails
1060     */
1061    private ObjectName jmxRegister(final BaseObjectPoolConfig<T> config,
1062            final String jmxNameBase, String jmxNamePrefix) {
1063        ObjectName newObjectName = null;
1064        final MBeanServer mbs = ManagementFactory.getPlatformMBeanServer();
1065        int i = 1;
1066        boolean registered = false;
1067        String base = config.getJmxNameBase();
1068        if (base == null) {
1069            base = jmxNameBase;
1070        }
1071        while (!registered) {
1072            try {
1073                ObjectName objName;
1074                // Skip the numeric suffix for the first pool in case there is
1075                // only one so the names are cleaner.
1076                if (i == 1) {
1077                    objName = new ObjectName(base + jmxNamePrefix);
1078                } else {
1079                    objName = new ObjectName(base + jmxNamePrefix + i);
1080                }
1081                mbs.registerMBean(this, objName);
1082                newObjectName = objName;
1083                registered = true;
1084            } catch (final MalformedObjectNameException e) {
1085                if (BaseObjectPoolConfig.DEFAULT_JMX_NAME_PREFIX.equals(
1086                        jmxNamePrefix) && jmxNameBase.equals(base)) {
1087                    // Shouldn't happen. Skip registration if it does.
1088                    registered = true;
1089                } else {
1090                    // Must be an invalid name. Use the defaults instead.
1091                    jmxNamePrefix =
1092                            BaseObjectPoolConfig.DEFAULT_JMX_NAME_PREFIX;
1093                    base = jmxNameBase;
1094                }
1095            } catch (final InstanceAlreadyExistsException e) {
1096                // Increment the index and try again
1097                i++;
1098            } catch (final MBeanRegistrationException | NotCompliantMBeanException e) {
1099                // Shouldn't happen. Skip registration if it does.
1100                registered = true;
1101            }
1102        }
1103        return newObjectName;
1104    }
1105
1106    /**
1107     * Gets the stack trace of an exception as a string.
1108     * @param e exception to trace
1109     * @return exception stack trace as a string
1110     */
1111    private String getStackTrace(final Exception e) {
1112        // Need the exception in string form to prevent the retention of
1113        // references to classes in the stack trace that could trigger a memory
1114        // leak in a container environment.
1115        final Writer w = new StringWriter();
1116        final PrintWriter pw = new PrintWriter(w);
1117        e.printStackTrace(pw);
1118        return w.toString();
1119    }
1120
1121    // Inner classes
1122
1123    /**
1124     * The idle object evictor {@link TimerTask}.
1125     *
1126     * @see GenericKeyedObjectPool#setTimeBetweenEvictionRunsMillis
1127     */
1128    class Evictor implements Runnable {
1129
1130        private ScheduledFuture<?> scheduledFuture;
1131
1132        /**
1133         * Run pool maintenance.  Evict objects qualifying for eviction and then
1134         * ensure that the minimum number of idle instances are available.
1135         * Since the Timer that invokes Evictors is shared for all Pools but
1136         * pools may exist in different class loaders, the Evictor ensures that
1137         * any actions taken are under the class loader of the factory
1138         * associated with the pool.
1139         */
1140        @Override
1141        public void run() {
1142            final ClassLoader savedClassLoader =
1143                    Thread.currentThread().getContextClassLoader();
1144            try {
1145                if (factoryClassLoader != null) {
1146                    // Set the class loader for the factory
1147                    final ClassLoader cl = factoryClassLoader.get();
1148                    if (cl == null) {
1149                        // The pool has been dereferenced and the class loader
1150                        // GC'd. Cancel this timer so the pool can be GC'd as
1151                        // well.
1152                        cancel();
1153                        return;
1154                    }
1155                    Thread.currentThread().setContextClassLoader(cl);
1156                }
1157
1158                // Evict from the pool
1159                try {
1160                    evict();
1161                } catch(final Exception e) {
1162                    swallowException(e);
1163                } catch(final OutOfMemoryError oome) {
1164                    // Log problem but give evictor thread a chance to continue
1165                    // in case error is recoverable
1166                    oome.printStackTrace(System.err);
1167                }
1168                // Re-create idle instances.
1169                try {
1170                    ensureMinIdle();
1171                } catch (final Exception e) {
1172                    swallowException(e);
1173                }
1174            } finally {
1175                // Restore the previous CCL
1176                Thread.currentThread().setContextClassLoader(savedClassLoader);
1177            }
1178        }
1179
1180
1181        /**
1182         * Sets the scheduled future.
1183         *
1184         * @param scheduledFuture the scheduled future.
1185         */
1186        void setScheduledFuture(final ScheduledFuture<?> scheduledFuture) {
1187            this.scheduledFuture = scheduledFuture;
1188        }
1189
1190
1191        /**
1192         * Cancels the scheduled future.
1193         */
1194        void cancel() {
1195            scheduledFuture.cancel(false);
1196        }
1197
1198    }
1199
1200    /**
1201     * Maintains a cache of values for a single metric and reports
1202     * statistics on the cached values.
1203     */
1204    private class StatsStore {
1205
1206        private final AtomicLong values[];
1207        private final int size;
1208        private int index;
1209
1210        /**
1211         * Create a StatsStore with the given cache size.
1212         *
1213         * @param size number of values to maintain in the cache.
1214         */
1215        public StatsStore(final int size) {
1216            this.size = size;
1217            values = new AtomicLong[size];
1218            for (int i = 0; i < size; i++) {
1219                values[i] = new AtomicLong(-1);
1220            }
1221        }
1222
1223        /**
1224         * Adds a value to the cache.  If the cache is full, one of the
1225         * existing values is replaced by the new value.
1226         *
1227         * @param value new value to add to the cache.
1228         */
1229        public synchronized void add(final long value) {
1230            values[index].set(value);
1231            index++;
1232            if (index == size) {
1233                index = 0;
1234            }
1235        }
1236
1237        /**
1238         * Returns the mean of the cached values.
1239         *
1240         * @return the mean of the cache, truncated to long
1241         */
1242        public long getMean() {
1243            double result = 0;
1244            int counter = 0;
1245            for (int i = 0; i < size; i++) {
1246                final long value = values[i].get();
1247                if (value != -1) {
1248                    counter++;
1249                    result = result * ((counter - 1) / (double) counter) +
1250                            value/(double) counter;
1251                }
1252            }
1253            return (long) result;
1254        }
1255
1256        @Override
1257        public String toString() {
1258            final StringBuilder builder = new StringBuilder();
1259            builder.append("StatsStore [values=");
1260            builder.append(Arrays.toString(values));
1261            builder.append(", size=");
1262            builder.append(size);
1263            builder.append(", index=");
1264            builder.append(index);
1265            builder.append("]");
1266            return builder.toString();
1267        }
1268    }
1269
1270    /**
1271     * The idle object eviction iterator. Holds a reference to the idle objects.
1272     */
1273    class EvictionIterator implements Iterator<PooledObject<T>> {
1274
1275        private final Deque<PooledObject<T>> idleObjects;
1276        private final Iterator<PooledObject<T>> idleObjectIterator;
1277
1278        /**
1279         * Create an EvictionIterator for the provided idle instance deque.
1280         * @param idleObjects underlying deque
1281         */
1282        EvictionIterator(final Deque<PooledObject<T>> idleObjects) {
1283            this.idleObjects = idleObjects;
1284
1285            if (getLifo()) {
1286                idleObjectIterator = idleObjects.descendingIterator();
1287            } else {
1288                idleObjectIterator = idleObjects.iterator();
1289            }
1290        }
1291
1292        /**
1293         * Returns the idle object deque referenced by this iterator.
1294         * @return the idle object deque
1295         */
1296        public Deque<PooledObject<T>> getIdleObjects() {
1297            return idleObjects;
1298        }
1299
1300        /** {@inheritDoc} */
1301        @Override
1302        public boolean hasNext() {
1303            return idleObjectIterator.hasNext();
1304        }
1305
1306        /** {@inheritDoc} */
1307        @Override
1308        public PooledObject<T> next() {
1309            return idleObjectIterator.next();
1310        }
1311
1312        /** {@inheritDoc} */
1313        @Override
1314        public void remove() {
1315            idleObjectIterator.remove();
1316        }
1317
1318    }
1319
1320    /**
1321     * Wrapper for objects under management by the pool.
1322     *
1323     * GenericObjectPool and GenericKeyedObjectPool maintain references to all
1324     * objects under management using maps keyed on the objects. This wrapper
1325     * class ensures that objects can work as hash keys.
1326     *
1327     * @param <T> type of objects in the pool
1328     */
1329    static class IdentityWrapper<T> {
1330        /** Wrapped object */
1331        private final T instance;
1332
1333        /**
1334         * Create a wrapper for an instance.
1335         *
1336         * @param instance object to wrap
1337         */
1338        public IdentityWrapper(final T instance) {
1339            this.instance = instance;
1340        }
1341
1342        @Override
1343        public int hashCode() {
1344            return System.identityHashCode(instance);
1345        }
1346
1347        @Override
1348        @SuppressWarnings("rawtypes")
1349        public boolean equals(final Object other) {
1350            return  other instanceof IdentityWrapper &&
1351                    ((IdentityWrapper) other).instance == instance;
1352        }
1353
1354        /**
1355         * @return the wrapped object
1356         */
1357        public T getObject() {
1358            return instance;
1359        }
1360
1361        @Override
1362        public String toString() {
1363            final StringBuilder builder = new StringBuilder();
1364            builder.append("IdentityWrapper [instance=");
1365            builder.append(instance);
1366            builder.append("]");
1367            return builder.toString();
1368        }
1369    }
1370
1371    @Override
1372    protected void toStringAppendFields(final StringBuilder builder) {
1373        builder.append("maxTotal=");
1374        builder.append(maxTotal);
1375        builder.append(", blockWhenExhausted=");
1376        builder.append(blockWhenExhausted);
1377        builder.append(", maxWaitMillis=");
1378        builder.append(maxWaitMillis);
1379        builder.append(", lifo=");
1380        builder.append(lifo);
1381        builder.append(", fairness=");
1382        builder.append(fairness);
1383        builder.append(", testOnCreate=");
1384        builder.append(testOnCreate);
1385        builder.append(", testOnBorrow=");
1386        builder.append(testOnBorrow);
1387        builder.append(", testOnReturn=");
1388        builder.append(testOnReturn);
1389        builder.append(", testWhileIdle=");
1390        builder.append(testWhileIdle);
1391        builder.append(", timeBetweenEvictionRunsMillis=");
1392        builder.append(timeBetweenEvictionRunsMillis);
1393        builder.append(", numTestsPerEvictionRun=");
1394        builder.append(numTestsPerEvictionRun);
1395        builder.append(", minEvictableIdleTimeMillis=");
1396        builder.append(minEvictableIdleTimeMillis);
1397        builder.append(", softMinEvictableIdleTimeMillis=");
1398        builder.append(softMinEvictableIdleTimeMillis);
1399        builder.append(", evictionPolicy=");
1400        builder.append(evictionPolicy);
1401        builder.append(", closeLock=");
1402        builder.append(closeLock);
1403        builder.append(", closed=");
1404        builder.append(closed);
1405        builder.append(", evictionLock=");
1406        builder.append(evictionLock);
1407        builder.append(", evictor=");
1408        builder.append(evictor);
1409        builder.append(", evictionIterator=");
1410        builder.append(evictionIterator);
1411        builder.append(", factoryClassLoader=");
1412        builder.append(factoryClassLoader);
1413        builder.append(", oname=");
1414        builder.append(objectName);
1415        builder.append(", creationStackTrace=");
1416        builder.append(creationStackTrace);
1417        builder.append(", borrowedCount=");
1418        builder.append(borrowedCount);
1419        builder.append(", returnedCount=");
1420        builder.append(returnedCount);
1421        builder.append(", createdCount=");
1422        builder.append(createdCount);
1423        builder.append(", destroyedCount=");
1424        builder.append(destroyedCount);
1425        builder.append(", destroyedByEvictorCount=");
1426        builder.append(destroyedByEvictorCount);
1427        builder.append(", destroyedByBorrowValidationCount=");
1428        builder.append(destroyedByBorrowValidationCount);
1429        builder.append(", activeTimes=");
1430        builder.append(activeTimes);
1431        builder.append(", idleTimes=");
1432        builder.append(idleTimes);
1433        builder.append(", waitTimes=");
1434        builder.append(waitTimes);
1435        builder.append(", maxBorrowWaitTimeMillis=");
1436        builder.append(maxBorrowWaitTimeMillis);
1437        builder.append(", swallowedExceptionListener=");
1438        builder.append(swallowedExceptionListener);
1439    }
1440
1441
1442}