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