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()</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            if (null != evictor) {
776                EvictionTimer.cancel(evictor, evictorShutdownTimeoutMillis, TimeUnit.MILLISECONDS);
777                evictor = null;
778                evictionIterator = null;
779            }
780            if (delay > 0) {
781                evictor = new Evictor();
782                EvictionTimer.schedule(evictor, delay, delay);
783            }
784        }
785    }
786
787    /**
788     * Stops the evictor.
789     */
790    void stopEvitor() {
791        startEvictor(-1L);
792    }
793    /**
794     * Tries to ensure that the configured minimum number of idle instances are
795     * available in the pool.
796     * @throws Exception if an error occurs creating idle instances
797     */
798    abstract void ensureMinIdle() throws Exception;
799
800
801    // Monitoring (primarily JMX) related methods
802
803    /**
804     * Provides the name under which the pool has been registered with the
805     * platform MBean server or <code>null</code> if the pool has not been
806     * registered.
807     * @return the JMX name
808     */
809    public final ObjectName getJmxName() {
810        return objectName;
811    }
812
813    /**
814     * Provides the stack trace for the call that created this pool. JMX
815     * registration may trigger a memory leak so it is important that pools are
816     * deregistered when no longer used by calling the {@link #close()} method.
817     * This method is provided to assist with identifying code that creates but
818     * does not close it thereby creating a memory leak.
819     * @return pool creation stack trace
820     */
821    public final String getCreationStackTrace() {
822        return creationStackTrace;
823    }
824
825    /**
826     * The total number of objects successfully borrowed from this pool over the
827     * lifetime of the pool.
828     * @return the borrowed object count
829     */
830    public final long getBorrowedCount() {
831        return borrowedCount.get();
832    }
833
834    /**
835     * The total number of objects returned to this pool over the lifetime of
836     * the pool. This excludes attempts to return the same object multiple
837     * times.
838     * @return the returned object count
839     */
840    public final long getReturnedCount() {
841        return returnedCount.get();
842    }
843
844    /**
845     * The total number of objects created for this pool over the lifetime of
846     * the pool.
847     * @return the created object count
848     */
849    public final long getCreatedCount() {
850        return createdCount.get();
851    }
852
853    /**
854     * The total number of objects destroyed by this pool over the lifetime of
855     * the pool.
856     * @return the destroyed object count
857     */
858    public final long getDestroyedCount() {
859        return destroyedCount.get();
860    }
861
862    /**
863     * The total number of objects destroyed by the evictor associated with this
864     * pool over the lifetime of the pool.
865     * @return the evictor destroyed object count
866     */
867    public final long getDestroyedByEvictorCount() {
868        return destroyedByEvictorCount.get();
869    }
870
871    /**
872     * The total number of objects destroyed by this pool as a result of failing
873     * validation during <code>borrowObject()</code> over the lifetime of the
874     * pool.
875     * @return validation destroyed object count
876     */
877    public final long getDestroyedByBorrowValidationCount() {
878        return destroyedByBorrowValidationCount.get();
879    }
880
881    /**
882     * The mean time objects are active for based on the last {@link
883     * #MEAN_TIMING_STATS_CACHE_SIZE} objects returned to the pool.
884     * @return mean time an object has been checked out from the pool among
885     * recently returned objects
886     */
887    public final long getMeanActiveTimeMillis() {
888        return activeTimes.getMean();
889    }
890
891    /**
892     * The mean time objects are idle for based on the last {@link
893     * #MEAN_TIMING_STATS_CACHE_SIZE} objects borrowed from the pool.
894     * @return mean time an object has been idle in the pool among recently
895     * borrowed objects
896     */
897    public final long getMeanIdleTimeMillis() {
898        return idleTimes.getMean();
899    }
900
901    /**
902     * The mean time threads wait to borrow an object based on the last {@link
903     * #MEAN_TIMING_STATS_CACHE_SIZE} objects borrowed from the pool.
904     * @return mean time in milliseconds that a recently served thread has had
905     * to wait to borrow an object from the pool
906     */
907    public final long getMeanBorrowWaitTimeMillis() {
908        return waitTimes.getMean();
909    }
910
911    /**
912     * The maximum time a thread has waited to borrow objects from the pool.
913     * @return maximum wait time in milliseconds since the pool was created
914     */
915    public final long getMaxBorrowWaitTimeMillis() {
916        return maxBorrowWaitTimeMillis.get();
917    }
918
919    /**
920     * The number of instances currently idle in this pool.
921     * @return count of instances available for checkout from the pool
922     */
923    public abstract int getNumIdle();
924
925    /**
926     * The listener used (if any) to receive notifications of exceptions
927     * unavoidably swallowed by the pool.
928     *
929     * @return The listener or <code>null</code> for no listener
930     */
931    public final SwallowedExceptionListener getSwallowedExceptionListener() {
932        return swallowedExceptionListener;
933    }
934
935    /**
936     * The listener used (if any) to receive notifications of exceptions
937     * unavoidably swallowed by the pool.
938     *
939     * @param swallowedExceptionListener    The listener or <code>null</code>
940     *                                      for no listener
941     */
942    public final void setSwallowedExceptionListener(
943            final SwallowedExceptionListener swallowedExceptionListener) {
944        this.swallowedExceptionListener = swallowedExceptionListener;
945    }
946
947    /**
948     * Swallows an exception and notifies the configured listener for swallowed
949     * exceptions queue.
950     *
951     * @param swallowException exception to be swallowed
952     */
953    final void swallowException(final Exception swallowException) {
954        final SwallowedExceptionListener listener = getSwallowedExceptionListener();
955
956        if (listener == null) {
957            return;
958        }
959
960        try {
961            listener.onSwallowException(swallowException);
962        } catch (final VirtualMachineError e) {
963            throw e;
964        } catch (final Throwable t) {
965            // Ignore. Enjoy the irony.
966        }
967    }
968
969    /**
970     * Updates statistics after an object is borrowed from the pool.
971     * @param p object borrowed from the pool
972     * @param waitTime time (in milliseconds) that the borrowing thread had to wait
973     */
974    final void updateStatsBorrow(final PooledObject<T> p, final long waitTime) {
975        borrowedCount.incrementAndGet();
976        idleTimes.add(p.getIdleTimeMillis());
977        waitTimes.add(waitTime);
978
979        // lock-free optimistic-locking maximum
980        long currentMax;
981        do {
982            currentMax = maxBorrowWaitTimeMillis.get();
983            if (currentMax >= waitTime) {
984                break;
985            }
986        } while (!maxBorrowWaitTimeMillis.compareAndSet(currentMax, waitTime));
987    }
988
989    /**
990     * Updates statistics after an object is returned to the pool.
991     * @param activeTime the amount of time (in milliseconds) that the returning
992     * object was checked out
993     */
994    final void updateStatsReturn(final long activeTime) {
995        returnedCount.incrementAndGet();
996        activeTimes.add(activeTime);
997    }
998
999    /**
1000     * Marks the object as returning to the pool.
1001     * @param pooledObject instance to return to the keyed pool
1002     */
1003    protected void markReturningState(final PooledObject<T> pooledObject) {
1004        synchronized(pooledObject) {
1005            final PooledObjectState state = pooledObject.getState();
1006            if (state != PooledObjectState.ALLOCATED) {
1007                throw new IllegalStateException(
1008                        "Object has already been returned to this pool or is invalid");
1009            }
1010            pooledObject.markReturning(); // Keep from being marked abandoned
1011        }
1012    }
1013
1014    /**
1015     * Unregisters this pool's MBean.
1016     */
1017    final void jmxUnregister() {
1018        if (objectName != null) {
1019            try {
1020                ManagementFactory.getPlatformMBeanServer().unregisterMBean(
1021                        objectName);
1022            } catch (final MBeanRegistrationException | InstanceNotFoundException e) {
1023                swallowException(e);
1024            }
1025        }
1026    }
1027
1028    /**
1029     * Registers the pool with the platform MBean server.
1030     * The registered name will be
1031     * <code>jmxNameBase + jmxNamePrefix + i</code> where i is the least
1032     * integer greater than or equal to 1 such that the name is not already
1033     * registered. Swallows MBeanRegistrationException, NotCompliantMBeanException
1034     * returning null.
1035     *
1036     * @param config Pool configuration
1037     * @param jmxNameBase default base JMX name for this pool
1038     * @param jmxNamePrefix name prefix
1039     * @return registered ObjectName, null if registration fails
1040     */
1041    private ObjectName jmxRegister(final BaseObjectPoolConfig<T> config,
1042            final String jmxNameBase, String jmxNamePrefix) {
1043        ObjectName newObjectName = null;
1044        final MBeanServer mbs = ManagementFactory.getPlatformMBeanServer();
1045        int i = 1;
1046        boolean registered = false;
1047        String base = config.getJmxNameBase();
1048        if (base == null) {
1049            base = jmxNameBase;
1050        }
1051        while (!registered) {
1052            try {
1053                ObjectName objName;
1054                // Skip the numeric suffix for the first pool in case there is
1055                // only one so the names are cleaner.
1056                if (i == 1) {
1057                    objName = new ObjectName(base + jmxNamePrefix);
1058                } else {
1059                    objName = new ObjectName(base + jmxNamePrefix + i);
1060                }
1061                mbs.registerMBean(this, objName);
1062                newObjectName = objName;
1063                registered = true;
1064            } catch (final MalformedObjectNameException e) {
1065                if (BaseObjectPoolConfig.DEFAULT_JMX_NAME_PREFIX.equals(
1066                        jmxNamePrefix) && jmxNameBase.equals(base)) {
1067                    // Shouldn't happen. Skip registration if it does.
1068                    registered = true;
1069                } else {
1070                    // Must be an invalid name. Use the defaults instead.
1071                    jmxNamePrefix =
1072                            BaseObjectPoolConfig.DEFAULT_JMX_NAME_PREFIX;
1073                    base = jmxNameBase;
1074                }
1075            } catch (final InstanceAlreadyExistsException e) {
1076                // Increment the index and try again
1077                i++;
1078            } catch (final MBeanRegistrationException | NotCompliantMBeanException e) {
1079                // Shouldn't happen. Skip registration if it does.
1080                registered = true;
1081            }
1082        }
1083        return newObjectName;
1084    }
1085
1086    /**
1087     * Gets the stack trace of an exception as a string.
1088     * @param e exception to trace
1089     * @return exception stack trace as a string
1090     */
1091    private String getStackTrace(final Exception e) {
1092        // Need the exception in string form to prevent the retention of
1093        // references to classes in the stack trace that could trigger a memory
1094        // leak in a container environment.
1095        final Writer w = new StringWriter();
1096        final PrintWriter pw = new PrintWriter(w);
1097        e.printStackTrace(pw);
1098        return w.toString();
1099    }
1100
1101    // Inner classes
1102
1103    /**
1104     * The idle object evictor {@link TimerTask}.
1105     *
1106     * @see GenericKeyedObjectPool#setTimeBetweenEvictionRunsMillis
1107     */
1108    class Evictor implements Runnable {
1109
1110        private ScheduledFuture<?> scheduledFuture;
1111
1112        /**
1113         * Run pool maintenance.  Evict objects qualifying for eviction and then
1114         * ensure that the minimum number of idle instances are available.
1115         * Since the Timer that invokes Evictors is shared for all Pools but
1116         * pools may exist in different class loaders, the Evictor ensures that
1117         * any actions taken are under the class loader of the factory
1118         * associated with the pool.
1119         */
1120        @Override
1121        public void run() {
1122            final ClassLoader savedClassLoader =
1123                    Thread.currentThread().getContextClassLoader();
1124            try {
1125                if (factoryClassLoader != null) {
1126                    // Set the class loader for the factory
1127                    final ClassLoader cl = factoryClassLoader.get();
1128                    if (cl == null) {
1129                        // The pool has been dereferenced and the class loader
1130                        // GC'd. Cancel this timer so the pool can be GC'd as
1131                        // well.
1132                        cancel();
1133                        return;
1134                    }
1135                    Thread.currentThread().setContextClassLoader(cl);
1136                }
1137
1138                // Evict from the pool
1139                try {
1140                    evict();
1141                } catch(final Exception e) {
1142                    swallowException(e);
1143                } catch(final OutOfMemoryError oome) {
1144                    // Log problem but give evictor thread a chance to continue
1145                    // in case error is recoverable
1146                    oome.printStackTrace(System.err);
1147                }
1148                // Re-create idle instances.
1149                try {
1150                    ensureMinIdle();
1151                } catch (final Exception e) {
1152                    swallowException(e);
1153                }
1154            } finally {
1155                // Restore the previous CCL
1156                Thread.currentThread().setContextClassLoader(savedClassLoader);
1157            }
1158        }
1159
1160
1161        void setScheduledFuture(final ScheduledFuture<?> scheduledFuture) {
1162            this.scheduledFuture = scheduledFuture;
1163        }
1164
1165
1166        void cancel() {
1167            scheduledFuture.cancel(false);
1168        }
1169    }
1170
1171    /**
1172     * Maintains a cache of values for a single metric and reports
1173     * statistics on the cached values.
1174     */
1175    private class StatsStore {
1176
1177        private final AtomicLong values[];
1178        private final int size;
1179        private int index;
1180
1181        /**
1182         * Create a StatsStore with the given cache size.
1183         *
1184         * @param size number of values to maintain in the cache.
1185         */
1186        public StatsStore(final int size) {
1187            this.size = size;
1188            values = new AtomicLong[size];
1189            for (int i = 0; i < size; i++) {
1190                values[i] = new AtomicLong(-1);
1191            }
1192        }
1193
1194        /**
1195         * Adds a value to the cache.  If the cache is full, one of the
1196         * existing values is replaced by the new value.
1197         *
1198         * @param value new value to add to the cache.
1199         */
1200        public synchronized void add(final long value) {
1201            values[index].set(value);
1202            index++;
1203            if (index == size) {
1204                index = 0;
1205            }
1206        }
1207
1208        /**
1209         * Returns the mean of the cached values.
1210         *
1211         * @return the mean of the cache, truncated to long
1212         */
1213        public long getMean() {
1214            double result = 0;
1215            int counter = 0;
1216            for (int i = 0; i < size; i++) {
1217                final long value = values[i].get();
1218                if (value != -1) {
1219                    counter++;
1220                    result = result * ((counter - 1) / (double) counter) +
1221                            value/(double) counter;
1222                }
1223            }
1224            return (long) result;
1225        }
1226
1227        @Override
1228        public String toString() {
1229            final StringBuilder builder = new StringBuilder();
1230            builder.append("StatsStore [values=");
1231            builder.append(Arrays.toString(values));
1232            builder.append(", size=");
1233            builder.append(size);
1234            builder.append(", index=");
1235            builder.append(index);
1236            builder.append("]");
1237            return builder.toString();
1238        }
1239    }
1240
1241    /**
1242     * The idle object eviction iterator. Holds a reference to the idle objects.
1243     */
1244    class EvictionIterator implements Iterator<PooledObject<T>> {
1245
1246        private final Deque<PooledObject<T>> idleObjects;
1247        private final Iterator<PooledObject<T>> idleObjectIterator;
1248
1249        /**
1250         * Create an EvictionIterator for the provided idle instance deque.
1251         * @param idleObjects underlying deque
1252         */
1253        EvictionIterator(final Deque<PooledObject<T>> idleObjects) {
1254            this.idleObjects = idleObjects;
1255
1256            if (getLifo()) {
1257                idleObjectIterator = idleObjects.descendingIterator();
1258            } else {
1259                idleObjectIterator = idleObjects.iterator();
1260            }
1261        }
1262
1263        /**
1264         * Returns the idle object deque referenced by this iterator.
1265         * @return the idle object deque
1266         */
1267        public Deque<PooledObject<T>> getIdleObjects() {
1268            return idleObjects;
1269        }
1270
1271        /** {@inheritDoc} */
1272        @Override
1273        public boolean hasNext() {
1274            return idleObjectIterator.hasNext();
1275        }
1276
1277        /** {@inheritDoc} */
1278        @Override
1279        public PooledObject<T> next() {
1280            return idleObjectIterator.next();
1281        }
1282
1283        /** {@inheritDoc} */
1284        @Override
1285        public void remove() {
1286            idleObjectIterator.remove();
1287        }
1288
1289    }
1290
1291    /**
1292     * Wrapper for objects under management by the pool.
1293     *
1294     * GenericObjectPool and GenericKeyedObjectPool maintain references to all
1295     * objects under management using maps keyed on the objects. This wrapper
1296     * class ensures that objects can work as hash keys.
1297     *
1298     * @param <T> type of objects in the pool
1299     */
1300    static class IdentityWrapper<T> {
1301        /** Wrapped object */
1302        private final T instance;
1303
1304        /**
1305         * Create a wrapper for an instance.
1306         *
1307         * @param instance object to wrap
1308         */
1309        public IdentityWrapper(final T instance) {
1310            this.instance = instance;
1311        }
1312
1313        @Override
1314        public int hashCode() {
1315            return System.identityHashCode(instance);
1316        }
1317
1318        @Override
1319        @SuppressWarnings("rawtypes")
1320        public boolean equals(final Object other) {
1321            return  other instanceof IdentityWrapper &&
1322                    ((IdentityWrapper) other).instance == instance;
1323        }
1324
1325        /**
1326         * @return the wrapped object
1327         */
1328        public T getObject() {
1329            return instance;
1330        }
1331
1332        @Override
1333        public String toString() {
1334            final StringBuilder builder = new StringBuilder();
1335            builder.append("IdentityWrapper [instance=");
1336            builder.append(instance);
1337            builder.append("]");
1338            return builder.toString();
1339        }
1340    }
1341
1342    @Override
1343    protected void toStringAppendFields(final StringBuilder builder) {
1344        builder.append("maxTotal=");
1345        builder.append(maxTotal);
1346        builder.append(", blockWhenExhausted=");
1347        builder.append(blockWhenExhausted);
1348        builder.append(", maxWaitMillis=");
1349        builder.append(maxWaitMillis);
1350        builder.append(", lifo=");
1351        builder.append(lifo);
1352        builder.append(", fairness=");
1353        builder.append(fairness);
1354        builder.append(", testOnCreate=");
1355        builder.append(testOnCreate);
1356        builder.append(", testOnBorrow=");
1357        builder.append(testOnBorrow);
1358        builder.append(", testOnReturn=");
1359        builder.append(testOnReturn);
1360        builder.append(", testWhileIdle=");
1361        builder.append(testWhileIdle);
1362        builder.append(", timeBetweenEvictionRunsMillis=");
1363        builder.append(timeBetweenEvictionRunsMillis);
1364        builder.append(", numTestsPerEvictionRun=");
1365        builder.append(numTestsPerEvictionRun);
1366        builder.append(", minEvictableIdleTimeMillis=");
1367        builder.append(minEvictableIdleTimeMillis);
1368        builder.append(", softMinEvictableIdleTimeMillis=");
1369        builder.append(softMinEvictableIdleTimeMillis);
1370        builder.append(", evictionPolicy=");
1371        builder.append(evictionPolicy);
1372        builder.append(", closeLock=");
1373        builder.append(closeLock);
1374        builder.append(", closed=");
1375        builder.append(closed);
1376        builder.append(", evictionLock=");
1377        builder.append(evictionLock);
1378        builder.append(", evictor=");
1379        builder.append(evictor);
1380        builder.append(", evictionIterator=");
1381        builder.append(evictionIterator);
1382        builder.append(", factoryClassLoader=");
1383        builder.append(factoryClassLoader);
1384        builder.append(", oname=");
1385        builder.append(objectName);
1386        builder.append(", creationStackTrace=");
1387        builder.append(creationStackTrace);
1388        builder.append(", borrowedCount=");
1389        builder.append(borrowedCount);
1390        builder.append(", returnedCount=");
1391        builder.append(returnedCount);
1392        builder.append(", createdCount=");
1393        builder.append(createdCount);
1394        builder.append(", destroyedCount=");
1395        builder.append(destroyedCount);
1396        builder.append(", destroyedByEvictorCount=");
1397        builder.append(destroyedByEvictorCount);
1398        builder.append(", destroyedByBorrowValidationCount=");
1399        builder.append(destroyedByBorrowValidationCount);
1400        builder.append(", activeTimes=");
1401        builder.append(activeTimes);
1402        builder.append(", idleTimes=");
1403        builder.append(idleTimes);
1404        builder.append(", waitTimes=");
1405        builder.append(waitTimes);
1406        builder.append(", maxBorrowWaitTimeMillis=");
1407        builder.append(maxBorrowWaitTimeMillis);
1408        builder.append(", swallowedExceptionListener=");
1409        builder.append(swallowedExceptionListener);
1410    }
1411
1412
1413}