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