View Javadoc
1   /*
2    * Licensed to the Apache Software Foundation (ASF) under one or more
3    * contributor license agreements.  See the NOTICE file distributed with
4    * this work for additional information regarding copyright ownership.
5    * The ASF licenses this file to You under the Apache License, Version 2.0
6    * (the "License"); you may not use this file except in compliance with
7    * the License.  You may obtain a copy of the License at
8    *
9    *      http://www.apache.org/licenses/LICENSE-2.0
10   *
11   * Unless required by applicable law or agreed to in writing, software
12   * distributed under the License is distributed on an "AS IS" BASIS,
13   * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14   * See the License for the specific language governing permissions and
15   * limitations under the License.
16   */
17  package org.apache.commons.pool2.impl;
18  
19  import org.apache.commons.pool2.ObjectPool;
20  import org.apache.commons.pool2.PoolUtils;
21  import org.apache.commons.pool2.PooledObject;
22  import org.apache.commons.pool2.PooledObjectFactory;
23  import org.apache.commons.pool2.PooledObjectState;
24  import org.apache.commons.pool2.SwallowedExceptionListener;
25  import org.apache.commons.pool2.TrackedUse;
26  import org.apache.commons.pool2.UsageTracking;
27  
28  import java.util.ArrayList;
29  import java.util.HashSet;
30  import java.util.Iterator;
31  import java.util.Map;
32  import java.util.NoSuchElementException;
33  import java.util.Set;
34  import java.util.concurrent.ConcurrentHashMap;
35  import java.util.concurrent.TimeUnit;
36  import java.util.concurrent.atomic.AtomicLong;
37  
38  /**
39   * A configurable {@link ObjectPool} implementation.
40   * <p>
41   * When coupled with the appropriate {@link PooledObjectFactory},
42   * {@code GenericObjectPool} provides robust pooling functionality for
43   * arbitrary objects.
44   * </p>
45   * <p>
46   * Optionally, one may configure the pool to examine and possibly evict objects
47   * as they sit idle in the pool and to ensure that a minimum number of idle
48   * objects are available. This is performed by an "idle object eviction" thread,
49   * which runs asynchronously. Caution should be used when configuring this
50   * optional feature. Eviction runs contend with client threads for access to
51   * objects in the pool, so if they run too frequently performance issues may
52   * result.
53   * </p>
54   * <p>
55   * The pool can also be configured to detect and remove "abandoned" objects,
56   * i.e. objects that have been checked out of the pool but neither used nor
57   * returned before the configured
58   * {@link AbandonedConfig#getRemoveAbandonedTimeout() removeAbandonedTimeout}.
59   * Abandoned object removal can be configured to happen when
60   * {@code borrowObject} is invoked and the pool is close to starvation, or
61   * it can be executed by the idle object evictor, or both. If pooled objects
62   * implement the {@link TrackedUse} interface, their last use will be queried
63   * using the {@code getLastUsed} method on that interface; otherwise
64   * abandonment is determined by how long an object has been checked out from
65   * the pool.
66   * </p>
67   * <p>
68   * Implementation note: To prevent possible deadlocks, care has been taken to
69   * ensure that no call to a factory method will occur within a synchronization
70   * block. See POOL-125 and DBCP-44 for more information.
71   * </p>
72   * <p>
73   * This class is intended to be thread-safe.
74   * </p>
75   *
76   * @see GenericKeyedObjectPool
77   *
78   * @param <T> Type of element pooled in this pool.
79   *
80   * @since 2.0
81   */
82  public class GenericObjectPool<T> extends BaseGenericObjectPool<T>
83          implements ObjectPool<T>, GenericObjectPoolMXBean, UsageTracking<T> {
84  
85      /**
86       * Creates a new {@code GenericObjectPool} using defaults from
87       * {@link GenericObjectPoolConfig}.
88       *
89       * @param factory The object factory to be used to create object instances
90       *                used by this pool
91       */
92      public GenericObjectPool(final PooledObjectFactory<T> factory) {
93          this(factory, new GenericObjectPoolConfig<T>());
94      }
95  
96      /**
97       * Creates a new {@code GenericObjectPool} using a specific
98       * configuration.
99       *
100      * @param factory   The object factory to be used to create object instances
101      *                  used by this pool
102      * @param config    The configuration to use for this pool instance. The
103      *                  configuration is used by value. Subsequent changes to
104      *                  the configuration object will not be reflected in the
105      *                  pool.
106      */
107     public GenericObjectPool(final PooledObjectFactory<T> factory,
108             final GenericObjectPoolConfig<T> config) {
109 
110         super(config, ONAME_BASE, config.getJmxNamePrefix());
111 
112         if (factory == null) {
113             jmxUnregister(); // tidy up
114             throw new IllegalArgumentException("factory may not be null");
115         }
116         this.factory = factory;
117 
118         idleObjects = new LinkedBlockingDeque<>(config.getFairness());
119 
120         setConfig(config);
121     }
122 
123     /**
124      * Creates a new {@code GenericObjectPool} that tracks and destroys
125      * objects that are checked out, but never returned to the pool.
126      *
127      * @param factory   The object factory to be used to create object instances
128      *                  used by this pool
129      * @param config    The base pool configuration to use for this pool instance.
130      *                  The configuration is used by value. Subsequent changes to
131      *                  the configuration object will not be reflected in the
132      *                  pool.
133      * @param abandonedConfig  Configuration for abandoned object identification
134      *                         and removal.  The configuration is used by value.
135      */
136     public GenericObjectPool(final PooledObjectFactory<T> factory,
137             final GenericObjectPoolConfig<T> config, final AbandonedConfig abandonedConfig) {
138         this(factory, config);
139         setAbandonedConfig(abandonedConfig);
140     }
141 
142     /**
143      * Returns the cap on the number of "idle" instances in the pool. If maxIdle
144      * is set too low on heavily loaded systems it is possible you will see
145      * objects being destroyed and almost immediately new objects being created.
146      * This is a result of the active threads momentarily returning objects
147      * faster than they are requesting them, causing the number of idle
148      * objects to rise above maxIdle. The best value for maxIdle for heavily
149      * loaded system will vary but the default is a good starting point.
150      *
151      * @return the maximum number of "idle" instances that can be held in the
152      *         pool or a negative value if there is no limit
153      *
154      * @see #setMaxIdle
155      */
156     @Override
157     public int getMaxIdle() {
158         return maxIdle;
159     }
160 
161     /**
162      * Returns the cap on the number of "idle" instances in the pool. If maxIdle
163      * is set too low on heavily loaded systems it is possible you will see
164      * objects being destroyed and almost immediately new objects being created.
165      * This is a result of the active threads momentarily returning objects
166      * faster than they are requesting them, causing the number of idle
167      * objects to rise above maxIdle. The best value for maxIdle for heavily
168      * loaded system will vary but the default is a good starting point.
169      *
170      * @param maxIdle
171      *            The cap on the number of "idle" instances in the pool. Use a
172      *            negative value to indicate an unlimited number of idle
173      *            instances
174      *
175      * @see #getMaxIdle
176      */
177     public void setMaxIdle(final int maxIdle) {
178         this.maxIdle = maxIdle;
179     }
180 
181     /**
182      * Sets the target for the minimum number of idle objects to maintain in
183      * the pool. This setting only has an effect if it is positive and
184      * {@link #getTimeBetweenEvictionRunsMillis()} is greater than zero. If this
185      * is the case, an attempt is made to ensure that the pool has the required
186      * minimum number of instances during idle object eviction runs.
187      * <p>
188      * If the configured value of minIdle is greater than the configured value
189      * for maxIdle then the value of maxIdle will be used instead.
190      * </p>
191      *
192      * @param minIdle
193      *            The minimum number of objects.
194      *
195      * @see #getMinIdle()
196      * @see #getMaxIdle()
197      * @see #getTimeBetweenEvictionRunsMillis()
198      */
199     public void setMinIdle(final int minIdle) {
200         this.minIdle = minIdle;
201     }
202 
203     /**
204      * Returns the target for the minimum number of idle objects to maintain in
205      * the pool. This setting only has an effect if it is positive and
206      * {@link #getTimeBetweenEvictionRunsMillis()} is greater than zero. If this
207      * is the case, an attempt is made to ensure that the pool has the required
208      * minimum number of instances during idle object eviction runs.
209      * <p>
210      * If the configured value of minIdle is greater than the configured value
211      * for maxIdle then the value of maxIdle will be used instead.
212      * </p>
213      *
214      * @return The minimum number of objects.
215      *
216      * @see #setMinIdle(int)
217      * @see #setMaxIdle(int)
218      * @see #setTimeBetweenEvictionRunsMillis(long)
219      */
220     @Override
221     public int getMinIdle() {
222         final int maxIdleSave = getMaxIdle();
223         if (this.minIdle > maxIdleSave) {
224             return maxIdleSave;
225         }
226         return minIdle;
227     }
228 
229     /**
230      * Gets whether or not abandoned object removal is configured for this pool.
231      *
232      * @return true if this pool is configured to detect and remove
233      * abandoned objects
234      */
235     @Override
236     public boolean isAbandonedConfig() {
237         return abandonedConfig != null;
238     }
239 
240     /**
241      * Gets whether this pool identifies and logs any abandoned objects.
242      *
243      * @return {@code true} if abandoned object removal is configured for this
244      *         pool and removal events are to be logged otherwise {@code false}
245      *
246      * @see AbandonedConfig#getLogAbandoned()
247      */
248     @Override
249     public boolean getLogAbandoned() {
250         final AbandonedConfig ac = this.abandonedConfig;
251         return ac != null && ac.getLogAbandoned();
252     }
253 
254     /**
255      * Gets whether a check is made for abandoned objects when an object is borrowed
256      * from this pool.
257      *
258      * @return {@code true} if abandoned object removal is configured to be
259      *         activated by borrowObject otherwise {@code false}
260      *
261      * @see AbandonedConfig#getRemoveAbandonedOnBorrow()
262      */
263     @Override
264     public boolean getRemoveAbandonedOnBorrow() {
265         final AbandonedConfig ac = this.abandonedConfig;
266         return ac != null && ac.getRemoveAbandonedOnBorrow();
267     }
268 
269     /**
270      * Gets whether a check is made for abandoned objects when the evictor runs.
271      *
272      * @return {@code true} if abandoned object removal is configured to be
273      *         activated when the evictor runs otherwise {@code false}
274      *
275      * @see AbandonedConfig#getRemoveAbandonedOnMaintenance()
276      */
277     @Override
278     public boolean getRemoveAbandonedOnMaintenance() {
279         final AbandonedConfig ac = this.abandonedConfig;
280         return ac != null && ac.getRemoveAbandonedOnMaintenance();
281     }
282 
283     /**
284      * Obtains the timeout before which an object will be considered to be
285      * abandoned by this pool.
286      *
287      * @return The abandoned object timeout in seconds if abandoned object
288      *         removal is configured for this pool; Integer.MAX_VALUE otherwise.
289      *
290      * @see AbandonedConfig#getRemoveAbandonedTimeout()
291      */
292     @Override
293     public int getRemoveAbandonedTimeout() {
294         final AbandonedConfig ac = this.abandonedConfig;
295         return ac != null ? ac.getRemoveAbandonedTimeout() : Integer.MAX_VALUE;
296     }
297 
298 
299     /**
300      * Sets the base pool configuration.
301      *
302      * @param conf the new configuration to use. This is used by value.
303      *
304      * @see GenericObjectPoolConfig
305      */
306     public void setConfig(final GenericObjectPoolConfig<T> conf) {
307         super.setConfig(conf);
308         setMaxIdle(conf.getMaxIdle());
309         setMinIdle(conf.getMinIdle());
310         setMaxTotal(conf.getMaxTotal());
311     }
312 
313     /**
314      * Sets the abandoned object removal configuration.
315      *
316      * @param abandonedConfig the new configuration to use. This is used by value.
317      *
318      * @see AbandonedConfig
319      */
320     public void setAbandonedConfig(final AbandonedConfig abandonedConfig) {
321         if (abandonedConfig == null) {
322             this.abandonedConfig = null;
323         } else {
324             this.abandonedConfig = new AbandonedConfig();
325             this.abandonedConfig.setLogAbandoned(abandonedConfig.getLogAbandoned());
326             this.abandonedConfig.setLogWriter(abandonedConfig.getLogWriter());
327             this.abandonedConfig.setRemoveAbandonedOnBorrow(abandonedConfig.getRemoveAbandonedOnBorrow());
328             this.abandonedConfig.setRemoveAbandonedOnMaintenance(abandonedConfig.getRemoveAbandonedOnMaintenance());
329             this.abandonedConfig.setRemoveAbandonedTimeout(abandonedConfig.getRemoveAbandonedTimeout());
330             this.abandonedConfig.setUseUsageTracking(abandonedConfig.getUseUsageTracking());
331             this.abandonedConfig.setRequireFullStackTrace(abandonedConfig.getRequireFullStackTrace());
332         }
333     }
334 
335     /**
336      * Obtains a reference to the factory used to create, destroy and validate
337      * the objects used by this pool.
338      *
339      * @return the factory
340      */
341     public PooledObjectFactory<T> getFactory() {
342         return factory;
343     }
344 
345     /**
346      * Equivalent to <code>{@link #borrowObject(long)
347      * borrowObject}({@link #getMaxWaitMillis()})</code>.
348      * <p>
349      * {@inheritDoc}
350      * </p>
351      */
352     @Override
353     public T borrowObject() throws Exception {
354         return borrowObject(getMaxWaitMillis());
355     }
356 
357     /**
358      * Borrows an object from the pool using the specific waiting time which only
359      * applies if {@link #getBlockWhenExhausted()} is true.
360      * <p>
361      * If there is one or more idle instance available in the pool, then an
362      * idle instance will be selected based on the value of {@link #getLifo()},
363      * activated and returned. If activation fails, or {@link #getTestOnBorrow()
364      * testOnBorrow} is set to {@code true} and validation fails, the
365      * instance is destroyed and the next available instance is examined. This
366      * continues until either a valid instance is returned or there are no more
367      * idle instances available.
368      * </p>
369      * <p>
370      * If there are no idle instances available in the pool, behavior depends on
371      * the {@link #getMaxTotal() maxTotal}, (if applicable)
372      * {@link #getBlockWhenExhausted()} and the value passed in to the
373      * {@code borrowMaxWaitMillis} parameter. If the number of instances
374      * checked out from the pool is less than {@code maxTotal,} a new
375      * instance is created, activated and (if applicable) validated and returned
376      * to the caller. If validation fails, a {@code NoSuchElementException}
377      * is thrown.
378      * </p>
379      * <p>
380      * If the pool is exhausted (no available idle instances and no capacity to
381      * create new ones), this method will either block (if
382      * {@link #getBlockWhenExhausted()} is true) or throw a
383      * {@code NoSuchElementException} (if
384      * {@link #getBlockWhenExhausted()} is false). The length of time that this
385      * method will block when {@link #getBlockWhenExhausted()} is true is
386      * determined by the value passed in to the {@code borrowMaxWaitMillis}
387      * parameter.
388      * </p>
389      * <p>
390      * When the pool is exhausted, multiple calling threads may be
391      * simultaneously blocked waiting for instances to become available. A
392      * "fairness" algorithm has been implemented to ensure that threads receive
393      * available instances in request arrival order.
394      * </p>
395      *
396      * @param borrowMaxWaitMillis The time to wait in milliseconds for an object
397      *                            to become available
398      *
399      * @return object instance from the pool
400      *
401      * @throws NoSuchElementException if an instance cannot be returned
402      *
403      * @throws Exception if an object instance cannot be returned due to an
404      *                   error
405      */
406     public T borrowObject(final long borrowMaxWaitMillis) throws Exception {
407         assertOpen();
408 
409         final AbandonedConfig ac = this.abandonedConfig;
410         if (ac != null && ac.getRemoveAbandonedOnBorrow() &&
411                 (getNumIdle() < 2) &&
412                 (getNumActive() > getMaxTotal() - 3) ) {
413             removeAbandoned(ac);
414         }
415 
416         PooledObject<T> p = null;
417 
418         // Get local copy of current config so it is consistent for entire
419         // method execution
420         final boolean blockWhenExhausted = getBlockWhenExhausted();
421 
422         boolean create;
423         final long waitTime = System.currentTimeMillis();
424 
425         while (p == null) {
426             create = false;
427             p = idleObjects.pollFirst();
428             if (p == null) {
429                 p = create();
430                 if (p != null) {
431                     create = true;
432                 }
433             }
434             if (blockWhenExhausted) {
435                 if (p == null) {
436                     if (borrowMaxWaitMillis < 0) {
437                         p = idleObjects.takeFirst();
438                     } else {
439                         p = idleObjects.pollFirst(borrowMaxWaitMillis,
440                                 TimeUnit.MILLISECONDS);
441                     }
442                 }
443                 if (p == null) {
444                     throw new NoSuchElementException(
445                             "Timeout waiting for idle object");
446                 }
447             } else {
448                 if (p == null) {
449                     throw new NoSuchElementException("Pool exhausted");
450                 }
451             }
452             if (!p.allocate()) {
453                 p = null;
454             }
455 
456             if (p != null) {
457                 try {
458                     factory.activateObject(p);
459                 } catch (final Exception e) {
460                     try {
461                         destroy(p);
462                     } catch (final Exception e1) {
463                         // Ignore - activation failure is more important
464                     }
465                     p = null;
466                     if (create) {
467                         final NoSuchElementException nsee = new NoSuchElementException(
468                                 "Unable to activate object");
469                         nsee.initCause(e);
470                         throw nsee;
471                     }
472                 }
473                 if (p != null && getTestOnBorrow()) {
474                     boolean validate = false;
475                     Throwable validationThrowable = null;
476                     try {
477                         validate = factory.validateObject(p);
478                     } catch (final Throwable t) {
479                         PoolUtils.checkRethrow(t);
480                         validationThrowable = t;
481                     }
482                     if (!validate) {
483                         try {
484                             destroy(p);
485                             destroyedByBorrowValidationCount.incrementAndGet();
486                         } catch (final Exception e) {
487                             // Ignore - validation failure is more important
488                         }
489                         p = null;
490                         if (create) {
491                             final NoSuchElementException nsee = new NoSuchElementException(
492                                     "Unable to validate object");
493                             nsee.initCause(validationThrowable);
494                             throw nsee;
495                         }
496                     }
497                 }
498             }
499         }
500 
501         updateStatsBorrow(p, System.currentTimeMillis() - waitTime);
502 
503         return p.getObject();
504     }
505 
506     /**
507      * {@inheritDoc}
508      * <p>
509      * If {@link #getMaxIdle() maxIdle} is set to a positive value and the
510      * number of idle instances has reached this value, the returning instance
511      * is destroyed.
512      * </p>
513      * <p>
514      * If {@link #getTestOnReturn() testOnReturn} == true, the returning
515      * instance is validated before being returned to the idle instance pool. In
516      * this case, if validation fails, the instance is destroyed.
517      * </p>
518      * <p>
519      * Exceptions encountered destroying objects for any reason are swallowed
520      * but notified via a {@link SwallowedExceptionListener}.
521      * </p>
522      */
523     @Override
524     public void returnObject(final T obj) {
525         final PooledObject<T> p = allObjects.get(new IdentityWrapper<>(obj));
526 
527         if (p == null) {
528             if (!isAbandonedConfig()) {
529                 throw new IllegalStateException(
530                         "Returned object not currently part of this pool");
531             }
532             return; // Object was abandoned and removed
533         }
534 
535         markReturningState(p);
536 
537         final long activeTime = p.getActiveTimeMillis();
538 
539         if (getTestOnReturn() && !factory.validateObject(p)) {
540             try {
541                 destroy(p);
542             } catch (final Exception e) {
543                 swallowException(e);
544             }
545             try {
546                 ensureIdle(1, false);
547             } catch (final Exception e) {
548                 swallowException(e);
549             }
550             updateStatsReturn(activeTime);
551             return;
552         }
553 
554         try {
555             factory.passivateObject(p);
556         } catch (final Exception e1) {
557             swallowException(e1);
558             try {
559                 destroy(p);
560             } catch (final Exception e) {
561                 swallowException(e);
562             }
563             try {
564                 ensureIdle(1, false);
565             } catch (final Exception e) {
566                 swallowException(e);
567             }
568             updateStatsReturn(activeTime);
569             return;
570         }
571 
572         if (!p.deallocate()) {
573             throw new IllegalStateException(
574                     "Object has already been returned to this pool or is invalid");
575         }
576 
577         final int maxIdleSave = getMaxIdle();
578         if (isClosed() || maxIdleSave > -1 && maxIdleSave <= idleObjects.size()) {
579             try {
580                 destroy(p);
581             } catch (final Exception e) {
582                 swallowException(e);
583             }
584             try {
585                 ensureIdle(1, false);
586             } catch (final Exception e) {
587                 swallowException(e);
588             }
589         } else {
590             if (getLifo()) {
591                 idleObjects.addFirst(p);
592             } else {
593                 idleObjects.addLast(p);
594             }
595             if (isClosed()) {
596                 // Pool closed while object was being added to idle objects.
597                 // Make sure the returned object is destroyed rather than left
598                 // in the idle object pool (which would effectively be a leak)
599                 clear();
600             }
601         }
602         updateStatsReturn(activeTime);
603     }
604 
605     /**
606      * {@inheritDoc}
607      * <p>
608      * Activation of this method decrements the active count and attempts to
609      * destroy the instance.
610      * </p>
611      *
612      * @throws Exception             if an exception occurs destroying the
613      *                               object
614      * @throws IllegalStateException if obj does not belong to this pool
615      */
616     @Override
617     public void invalidateObject(final T obj) throws Exception {
618         final PooledObject<T> p = allObjects.get(new IdentityWrapper<>(obj));
619         if (p == null) {
620             if (isAbandonedConfig()) {
621                 return;
622             }
623             throw new IllegalStateException(
624                     "Invalidated object not currently part of this pool");
625         }
626         synchronized (p) {
627             if (p.getState() != PooledObjectState.INVALID) {
628                 destroy(p);
629             }
630         }
631         ensureIdle(1, false);
632     }
633 
634     /**
635      * Clears any objects sitting idle in the pool by removing them from the
636      * idle instance pool and then invoking the configured
637      * {@link PooledObjectFactory#destroyObject(PooledObject)} method on each
638      * idle instance.
639      * <p>
640      * Implementation notes:
641      * </p>
642      * <ul>
643      * <li>This method does not destroy or effect in any way instances that are
644      * checked out of the pool when it is invoked.</li>
645      * <li>Invoking this method does not prevent objects being returned to the
646      * idle instance pool, even during its execution. Additional instances may
647      * be returned while removed items are being destroyed.</li>
648      * <li>Exceptions encountered destroying idle instances are swallowed
649      * but notified via a {@link SwallowedExceptionListener}.</li>
650      * </ul>
651      */
652     @Override
653     public void clear() {
654         PooledObject<T> p = idleObjects.poll();
655 
656         while (p != null) {
657             try {
658                 destroy(p);
659             } catch (final Exception e) {
660                 swallowException(e);
661             }
662             p = idleObjects.poll();
663         }
664     }
665 
666     @Override
667     public int getNumActive() {
668         return allObjects.size() - idleObjects.size();
669     }
670 
671     @Override
672     public int getNumIdle() {
673         return idleObjects.size();
674     }
675 
676     /**
677      * Closes the pool. Once the pool is closed, {@link #borrowObject()} will
678      * fail with IllegalStateException, but {@link #returnObject(Object)} and
679      * {@link #invalidateObject(Object)} will continue to work, with returned
680      * objects destroyed on return.
681      * <p>
682      * Destroys idle instances in the pool by invoking {@link #clear()}.
683      * </p>
684      */
685     @Override
686     public void close() {
687         if (isClosed()) {
688             return;
689         }
690 
691         synchronized (closeLock) {
692             if (isClosed()) {
693                 return;
694             }
695 
696             // Stop the evictor before the pool is closed since evict() calls
697             // assertOpen()
698             stopEvictor();
699 
700             closed = true;
701             // This clear removes any idle objects
702             clear();
703 
704             jmxUnregister();
705 
706             // Release any threads that were waiting for an object
707             idleObjects.interuptTakeWaiters();
708         }
709     }
710 
711     /**
712      * {@inheritDoc}
713      * <p>
714      * Successive activations of this method examine objects in sequence,
715      * cycling through objects in oldest-to-youngest order.
716      * </p>
717      */
718     @Override
719     public void evict() throws Exception {
720         assertOpen();
721 
722         if (idleObjects.size() > 0) {
723 
724             PooledObject<T> underTest = null;
725             final EvictionPolicy<T> evictionPolicy = getEvictionPolicy();
726 
727             synchronized (evictionLock) {
728                 final EvictionConfigfig.html#EvictionConfig">EvictionConfig evictionConfig = new EvictionConfig(
729                         getMinEvictableIdleTimeMillis(),
730                         getSoftMinEvictableIdleTimeMillis(),
731                         getMinIdle());
732 
733                 final boolean testWhileIdle = getTestWhileIdle();
734 
735                 for (int i = 0, m = getNumTests(); i < m; i++) {
736                     if (evictionIterator == null || !evictionIterator.hasNext()) {
737                         evictionIterator = new EvictionIterator(idleObjects);
738                     }
739                     if (!evictionIterator.hasNext()) {
740                         // Pool exhausted, nothing to do here
741                         return;
742                     }
743 
744                     try {
745                         underTest = evictionIterator.next();
746                     } catch (final NoSuchElementException nsee) {
747                         // Object was borrowed in another thread
748                         // Don't count this as an eviction test so reduce i;
749                         i--;
750                         evictionIterator = null;
751                         continue;
752                     }
753 
754                     if (!underTest.startEvictionTest()) {
755                         // Object was borrowed in another thread
756                         // Don't count this as an eviction test so reduce i;
757                         i--;
758                         continue;
759                     }
760 
761                     // User provided eviction policy could throw all sorts of
762                     // crazy exceptions. Protect against such an exception
763                     // killing the eviction thread.
764                     boolean evict;
765                     try {
766                         evict = evictionPolicy.evict(evictionConfig, underTest,
767                                 idleObjects.size());
768                     } catch (final Throwable t) {
769                         // Slightly convoluted as SwallowedExceptionListener
770                         // uses Exception rather than Throwable
771                         PoolUtils.checkRethrow(t);
772                         swallowException(new Exception(t));
773                         // Don't evict on error conditions
774                         evict = false;
775                     }
776 
777                     if (evict) {
778                         destroy(underTest);
779                         destroyedByEvictorCount.incrementAndGet();
780                     } else {
781                         if (testWhileIdle) {
782                             boolean active = false;
783                             try {
784                                 factory.activateObject(underTest);
785                                 active = true;
786                             } catch (final Exception e) {
787                                 destroy(underTest);
788                                 destroyedByEvictorCount.incrementAndGet();
789                             }
790                             if (active) {
791                                 if (!factory.validateObject(underTest)) {
792                                     destroy(underTest);
793                                     destroyedByEvictorCount.incrementAndGet();
794                                 } else {
795                                     try {
796                                         factory.passivateObject(underTest);
797                                     } catch (final Exception e) {
798                                         destroy(underTest);
799                                         destroyedByEvictorCount.incrementAndGet();
800                                     }
801                                 }
802                             }
803                         }
804                         if (!underTest.endEvictionTest(idleObjects)) {
805                             // TODO - May need to add code here once additional
806                             // states are used
807                         }
808                     }
809                 }
810             }
811         }
812         final AbandonedConfig ac = this.abandonedConfig;
813         if (ac != null && ac.getRemoveAbandonedOnMaintenance()) {
814             removeAbandoned(ac);
815         }
816     }
817 
818     /**
819      * Tries to ensure that {@link #getMinIdle()} idle instances are available
820      * in the pool.
821      *
822      * @throws Exception If the associated factory throws an exception
823      * @since 2.4
824      */
825     public void preparePool() throws Exception {
826         if (getMinIdle() < 1) {
827             return;
828         }
829         ensureMinIdle();
830     }
831 
832     /**
833      * Attempts to create a new wrapped pooled object.
834      * <p>
835      * If there are {@link #getMaxTotal()} objects already in circulation
836      * or in process of being created, this method returns null.
837      * </p>
838      *
839      * @return The new wrapped pooled object
840      *
841      * @throws Exception if the object factory's {@code makeObject} fails
842      */
843     private PooledObject<T> create() throws Exception {
844         int localMaxTotal = getMaxTotal();
845         // This simplifies the code later in this method
846         if (localMaxTotal < 0) {
847             localMaxTotal = Integer.MAX_VALUE;
848         }
849 
850         final long localStartTimeMillis = System.currentTimeMillis();
851         final long localMaxWaitTimeMillis = Math.max(getMaxWaitMillis(), 0);
852 
853         // Flag that indicates if create should:
854         // - TRUE:  call the factory to create an object
855         // - FALSE: return null
856         // - null:  loop and re-test the condition that determines whether to
857         //          call the factory
858         Boolean create = null;
859         while (create == null) {
860             synchronized (makeObjectCountLock) {
861                 final long newCreateCount = createCount.incrementAndGet();
862                 if (newCreateCount > localMaxTotal) {
863                     // The pool is currently at capacity or in the process of
864                     // making enough new objects to take it to capacity.
865                     createCount.decrementAndGet();
866                     if (makeObjectCount == 0) {
867                         // There are no makeObject() calls in progress so the
868                         // pool is at capacity. Do not attempt to create a new
869                         // object. Return and wait for an object to be returned
870                         create = Boolean.FALSE;
871                     } else {
872                         // There are makeObject() calls in progress that might
873                         // bring the pool to capacity. Those calls might also
874                         // fail so wait until they complete and then re-test if
875                         // the pool is at capacity or not.
876                         makeObjectCountLock.wait(localMaxWaitTimeMillis);
877                     }
878                 } else {
879                     // The pool is not at capacity. Create a new object.
880                     makeObjectCount++;
881                     create = Boolean.TRUE;
882                 }
883             }
884 
885             // Do not block more if maxWaitTimeMillis is set.
886             if (create == null &&
887                 (localMaxWaitTimeMillis > 0 &&
888                  System.currentTimeMillis() - localStartTimeMillis >= localMaxWaitTimeMillis)) {
889                 create = Boolean.FALSE;
890             }
891         }
892 
893         if (!create.booleanValue()) {
894             return null;
895         }
896 
897         final PooledObject<T> p;
898         try {
899             p = factory.makeObject();
900             if (getTestOnCreate() && !factory.validateObject(p)) {
901                 createCount.decrementAndGet();
902                 return null;
903             }
904         } catch (final Throwable e) {
905             createCount.decrementAndGet();
906             throw e;
907         } finally {
908             synchronized (makeObjectCountLock) {
909                 makeObjectCount--;
910                 makeObjectCountLock.notifyAll();
911             }
912         }
913 
914         final AbandonedConfig ac = this.abandonedConfig;
915         if (ac != null && ac.getLogAbandoned()) {
916             p.setLogAbandoned(true);
917             p.setRequireFullStackTrace(ac.getRequireFullStackTrace());
918         }
919 
920         createdCount.incrementAndGet();
921         allObjects.put(new IdentityWrapper<>(p.getObject()), p);
922         return p;
923     }
924 
925     /**
926      * Destroys a wrapped pooled object.
927      *
928      * @param toDestroy The wrapped pooled object to destroy
929      *
930      * @throws Exception If the factory fails to destroy the pooled object
931      *                   cleanly
932      */
933     private void destroy(final PooledObject<T> toDestroy) throws Exception {
934         toDestroy.invalidate();
935         idleObjects.remove(toDestroy);
936         allObjects.remove(new IdentityWrapper<>(toDestroy.getObject()));
937         try {
938             factory.destroyObject(toDestroy);
939         } finally {
940             destroyedCount.incrementAndGet();
941             createCount.decrementAndGet();
942         }
943     }
944 
945     @Override
946     void ensureMinIdle() throws Exception {
947         ensureIdle(getMinIdle(), true);
948     }
949 
950     /**
951      * Tries to ensure that {@code idleCount} idle instances exist in the pool.
952      * <p>
953      * Creates and adds idle instances until either {@link #getNumIdle()} reaches {@code idleCount}
954      * or the total number of objects (idle, checked out, or being created) reaches
955      * {@link #getMaxTotal()}. If {@code always} is false, no instances are created unless
956      * there are threads waiting to check out instances from the pool.
957      * </p>
958      *
959      * @param idleCount the number of idle instances desired
960      * @param always true means create instances even if the pool has no threads waiting
961      * @throws Exception if the factory's makeObject throws
962      */
963     private void ensureIdle(final int idleCount, final boolean always) throws Exception {
964         if (idleCount < 1 || isClosed() || (!always && !idleObjects.hasTakeWaiters())) {
965             return;
966         }
967 
968         while (idleObjects.size() < idleCount) {
969             final PooledObject<T> p = create();
970             if (p == null) {
971                 // Can't create objects, no reason to think another call to
972                 // create will work. Give up.
973                 break;
974             }
975             if (getLifo()) {
976                 idleObjects.addFirst(p);
977             } else {
978                 idleObjects.addLast(p);
979             }
980         }
981         if (isClosed()) {
982             // Pool closed while object was being added to idle objects.
983             // Make sure the returned object is destroyed rather than left
984             // in the idle object pool (which would effectively be a leak)
985             clear();
986         }
987     }
988 
989     /**
990      * Creates an object, and place it into the pool. addObject() is useful for
991      * "pre-loading" a pool with idle objects.
992      * <p>
993      * If there is no capacity available to add to the pool, this is a no-op
994      * (no exception, no impact to the pool). </p>
995      */
996     @Override
997     public void addObject() throws Exception {
998         assertOpen();
999         if (factory == null) {
1000             throw new IllegalStateException(
1001                     "Cannot add objects without a factory.");
1002         }
1003         final PooledObject<T> p = create();
1004         addIdleObject(p);
1005     }
1006 
1007     /**
1008      * Adds the provided wrapped pooled object to the set of idle objects for
1009      * this pool. The object must already be part of the pool.  If {@code p}
1010      * is null, this is a no-op (no exception, but no impact on the pool).
1011      *
1012      * @param p The object to make idle
1013      *
1014      * @throws Exception If the factory fails to passivate the object
1015      */
1016     private void addIdleObject(final PooledObject<T> p) throws Exception {
1017         if (p != null) {
1018             factory.passivateObject(p);
1019             if (getLifo()) {
1020                 idleObjects.addFirst(p);
1021             } else {
1022                 idleObjects.addLast(p);
1023             }
1024         }
1025     }
1026 
1027     /**
1028      * Calculates the number of objects to test in a run of the idle object
1029      * evictor.
1030      *
1031      * @return The number of objects to test for validity
1032      */
1033     private int getNumTests() {
1034         final int numTestsPerEvictionRun = getNumTestsPerEvictionRun();
1035         if (numTestsPerEvictionRun >= 0) {
1036             return Math.min(numTestsPerEvictionRun, idleObjects.size());
1037         }
1038         return (int) (Math.ceil(idleObjects.size() /
1039                 Math.abs((double) numTestsPerEvictionRun)));
1040     }
1041 
1042     /**
1043      * Recovers abandoned objects which have been checked out but
1044      * not used since longer than the removeAbandonedTimeout.
1045      *
1046      * @param ac The configuration to use to identify abandoned objects
1047      */
1048     private void removeAbandoned(final AbandonedConfig ac) {
1049         // Generate a list of abandoned objects to remove
1050         final long now = System.currentTimeMillis();
1051         final long timeout =
1052                 now - (ac.getRemoveAbandonedTimeout() * 1000L);
1053         final ArrayList<PooledObject<T>> remove = new ArrayList<>();
1054         final Iterator<PooledObject<T>> it = allObjects.values().iterator();
1055         while (it.hasNext()) {
1056             final PooledObject<T> pooledObject = it.next();
1057             synchronized (pooledObject) {
1058                 if (pooledObject.getState() == PooledObjectState.ALLOCATED &&
1059                         pooledObject.getLastUsedTime() <= timeout) {
1060                     pooledObject.markAbandoned();
1061                     remove.add(pooledObject);
1062                 }
1063             }
1064         }
1065 
1066         // Now remove the abandoned objects
1067         final Iterator<PooledObject<T>> itr = remove.iterator();
1068         while (itr.hasNext()) {
1069             final PooledObject<T> pooledObject = itr.next();
1070             if (ac.getLogAbandoned()) {
1071                 pooledObject.printStackTrace(ac.getLogWriter());
1072             }
1073             try {
1074                 invalidateObject(pooledObject.getObject());
1075             } catch (final Exception e) {
1076                 e.printStackTrace();
1077             }
1078         }
1079     }
1080 
1081 
1082     //--- Usage tracking support -----------------------------------------------
1083 
1084     @Override
1085     public void use(final T pooledObject) {
1086         final AbandonedConfig ac = this.abandonedConfig;
1087         if (ac != null && ac.getUseUsageTracking()) {
1088             final PooledObject<T> wrapper = allObjects.get(new IdentityWrapper<>(pooledObject));
1089             wrapper.use();
1090         }
1091     }
1092 
1093 
1094     //--- JMX support ----------------------------------------------------------
1095 
1096     private volatile String factoryType = null;
1097 
1098     /**
1099      * Returns an estimate of the number of threads currently blocked waiting for
1100      * an object from the pool. This is intended for monitoring only, not for
1101      * synchronization control.
1102      *
1103      * @return The estimate of the number of threads currently blocked waiting
1104      *         for an object from the pool
1105      */
1106     @Override
1107     public int getNumWaiters() {
1108         if (getBlockWhenExhausted()) {
1109             return idleObjects.getTakeQueueLength();
1110         }
1111         return 0;
1112     }
1113 
1114     /**
1115      * Returns the type - including the specific type rather than the generic -
1116      * of the factory.
1117      *
1118      * @return A string representation of the factory type
1119      */
1120     @Override
1121     public String getFactoryType() {
1122         // Not thread safe. Accept that there may be multiple evaluations.
1123         if (factoryType == null) {
1124             final StringBuilder result = new StringBuilder();
1125             result.append(factory.getClass().getName());
1126             result.append('<');
1127             final Class<?> pooledObjectType =
1128                     PoolImplUtils.getFactoryType(factory.getClass());
1129             result.append(pooledObjectType.getName());
1130             result.append('>');
1131             factoryType = result.toString();
1132         }
1133         return factoryType;
1134     }
1135 
1136     /**
1137      * Provides information on all the objects in the pool, both idle (waiting
1138      * to be borrowed) and active (currently borrowed).
1139      * <p>
1140      * Note: This is named listAllObjects so it is presented as an operation via
1141      * JMX. That means it won't be invoked unless the explicitly requested
1142      * whereas all attributes will be automatically requested when viewing the
1143      * attributes for an object in a tool like JConsole.
1144      * </p>
1145      *
1146      * @return Information grouped on all the objects in the pool
1147      */
1148     @Override
1149     public Set<DefaultPooledObjectInfo> listAllObjects() {
1150         final Set<DefaultPooledObjectInfo> result =
1151                 new HashSet<>(allObjects.size());
1152         for (final PooledObject<T> p : allObjects.values()) {
1153             result.add(new DefaultPooledObjectInfo(p));
1154         }
1155         return result;
1156     }
1157 
1158     // --- configuration attributes --------------------------------------------
1159 
1160     private volatile int maxIdle = GenericObjectPoolConfig.DEFAULT_MAX_IDLE;
1161     private volatile int minIdle = GenericObjectPoolConfig.DEFAULT_MIN_IDLE;
1162     private final PooledObjectFactory<T> factory;
1163 
1164 
1165     // --- internal attributes -------------------------------------------------
1166 
1167     /*
1168      * All of the objects currently associated with this pool in any state. It
1169      * excludes objects that have been destroyed. The size of
1170      * {@link #allObjects} will always be less than or equal to {@link
1171      * #_maxActive}. Map keys are pooled objects, values are the PooledObject
1172      * wrappers used internally by the pool.
1173      */
1174     private final Map<IdentityWrapper<T>, PooledObject<T>> allObjects =
1175         new ConcurrentHashMap<>();
1176     /*
1177      * The combined count of the currently created objects and those in the
1178      * process of being created. Under load, it may exceed {@link #_maxActive}
1179      * if multiple threads try and create a new object at the same time but
1180      * {@link #create()} will ensure that there are never more than
1181      * {@link #_maxActive} objects created at any one time.
1182      */
1183     private final AtomicLong createCount = new AtomicLong(0);
1184     private long makeObjectCount = 0;
1185     private final Object makeObjectCountLock = new Object();
1186     private final LinkedBlockingDeque<PooledObject<T>> idleObjects;
1187 
1188     // JMX specific attributes
1189     private static final String ONAME_BASE =
1190         "org.apache.commons.pool2:type=GenericObjectPool,name=";
1191 
1192     // Additional configuration properties for abandoned object tracking
1193     private volatile AbandonedConfig abandonedConfig = null;
1194 
1195     @Override
1196     protected void toStringAppendFields(final StringBuilder builder) {
1197         super.toStringAppendFields(builder);
1198         builder.append(", factoryType=");
1199         builder.append(factoryType);
1200         builder.append(", maxIdle=");
1201         builder.append(maxIdle);
1202         builder.append(", minIdle=");
1203         builder.append(minIdle);
1204         builder.append(", factory=");
1205         builder.append(factory);
1206         builder.append(", allObjects=");
1207         builder.append(allObjects);
1208         builder.append(", createCount=");
1209         builder.append(createCount);
1210         builder.append(", idleObjects=");
1211         builder.append(idleObjects);
1212         builder.append(", abandonedConfig=");
1213         builder.append(abandonedConfig);
1214     }
1215 
1216 }