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 org.apache.commons.pool2.ObjectPool; 020import org.apache.commons.pool2.PoolUtils; 021import org.apache.commons.pool2.PooledObject; 022import org.apache.commons.pool2.PooledObjectFactory; 023import org.apache.commons.pool2.PooledObjectState; 024import org.apache.commons.pool2.SwallowedExceptionListener; 025import org.apache.commons.pool2.TrackedUse; 026import org.apache.commons.pool2.UsageTracking; 027 028import java.util.ArrayList; 029import java.util.HashSet; 030import java.util.Iterator; 031import java.util.Map; 032import java.util.NoSuchElementException; 033import java.util.Set; 034import java.util.concurrent.ConcurrentHashMap; 035import java.util.concurrent.TimeUnit; 036import java.util.concurrent.atomic.AtomicLong; 037 038/** 039 * A configurable {@link ObjectPool} implementation. 040 * <p> 041 * When coupled with the appropriate {@link PooledObjectFactory}, 042 * <code>GenericObjectPool</code> provides robust pooling functionality for 043 * arbitrary objects. 044 * </p> 045 * <p> 046 * Optionally, one may configure the pool to examine and possibly evict objects 047 * as they sit idle in the pool and to ensure that a minimum number of idle 048 * objects are available. This is performed by an "idle object eviction" thread, 049 * which runs asynchronously. Caution should be used when configuring this 050 * optional feature. Eviction runs contend with client threads for access to 051 * objects in the pool, so if they run too frequently performance issues may 052 * result. 053 * </p> 054 * <p> 055 * The pool can also be configured to detect and remove "abandoned" objects, 056 * i.e. objects that have been checked out of the pool but neither used nor 057 * returned before the configured 058 * {@link AbandonedConfig#getRemoveAbandonedTimeout() removeAbandonedTimeout}. 059 * Abandoned object removal can be configured to happen when 060 * <code>borrowObject</code> is invoked and the pool is close to starvation, or 061 * it can be executed by the idle object evictor, or both. If pooled objects 062 * implement the {@link TrackedUse} interface, their last use will be queried 063 * using the <code>getLastUsed</code> method on that interface; otherwise 064 * abandonment is determined by how long an object has been checked out from 065 * the pool. 066 * </p> 067 * <p> 068 * Implementation note: To prevent possible deadlocks, care has been taken to 069 * ensure that no call to a factory method will occur within a synchronization 070 * block. See POOL-125 and DBCP-44 for more information. 071 * </p> 072 * <p> 073 * This class is intended to be thread-safe. 074 * </p> 075 * 076 * @see GenericKeyedObjectPool 077 * 078 * @param <T> Type of element pooled in this pool. 079 * 080 * @since 2.0 081 */ 082public class GenericObjectPool<T> extends BaseGenericObjectPool<T> 083 implements ObjectPool<T>, GenericObjectPoolMXBean, UsageTracking<T> { 084 085 /** 086 * Creates a new <code>GenericObjectPool</code> using defaults from 087 * {@link GenericObjectPoolConfig}. 088 * 089 * @param factory The object factory to be used to create object instances 090 * used by this pool 091 */ 092 public GenericObjectPool(final PooledObjectFactory<T> factory) { 093 this(factory, new GenericObjectPoolConfig<T>()); 094 } 095 096 /** 097 * Creates a new <code>GenericObjectPool</code> using a specific 098 * configuration. 099 * 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</code> 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</code> 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</code> parameter. If the number of instances 374 * checked out from the pool is less than <code>maxTotal,</code> a new 375 * instance is created, activated and (if applicable) validated and returned 376 * to the caller. If validation fails, a <code>NoSuchElementException</code> 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</code> (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</code> 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 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}