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 setLifo(conf.getLifo()); 301 setMaxIdle(conf.getMaxIdle()); 302 setMinIdle(conf.getMinIdle()); 303 setMaxTotal(conf.getMaxTotal()); 304 setMaxWaitMillis(conf.getMaxWaitMillis()); 305 setBlockWhenExhausted(conf.getBlockWhenExhausted()); 306 setTestOnCreate(conf.getTestOnCreate()); 307 setTestOnBorrow(conf.getTestOnBorrow()); 308 setTestOnReturn(conf.getTestOnReturn()); 309 setTestWhileIdle(conf.getTestWhileIdle()); 310 setNumTestsPerEvictionRun(conf.getNumTestsPerEvictionRun()); 311 setMinEvictableIdleTimeMillis(conf.getMinEvictableIdleTimeMillis()); 312 setTimeBetweenEvictionRunsMillis(conf.getTimeBetweenEvictionRunsMillis()); 313 setSoftMinEvictableIdleTimeMillis(conf.getSoftMinEvictableIdleTimeMillis()); 314 final EvictionPolicy<T> policy = conf.getEvictionPolicy(); 315 if (policy == null) { 316 // Use the class name (pre-2.6.0 compatible) 317 setEvictionPolicyClassName(conf.getEvictionPolicyClassName()); 318 } else { 319 // Otherwise, use the class (2.6.0 feature) 320 setEvictionPolicy(policy); 321 } 322 setEvictorShutdownTimeoutMillis(conf.getEvictorShutdownTimeoutMillis()); 323 } 324 325 /** 326 * Sets the abandoned object removal configuration. 327 * 328 * @param abandonedConfig the new configuration to use. This is used by value. 329 * 330 * @see AbandonedConfig 331 */ 332 public void setAbandonedConfig(final AbandonedConfig abandonedConfig) { 333 if (abandonedConfig == null) { 334 this.abandonedConfig = null; 335 } else { 336 this.abandonedConfig = new AbandonedConfig(); 337 this.abandonedConfig.setLogAbandoned(abandonedConfig.getLogAbandoned()); 338 this.abandonedConfig.setLogWriter(abandonedConfig.getLogWriter()); 339 this.abandonedConfig.setRemoveAbandonedOnBorrow(abandonedConfig.getRemoveAbandonedOnBorrow()); 340 this.abandonedConfig.setRemoveAbandonedOnMaintenance(abandonedConfig.getRemoveAbandonedOnMaintenance()); 341 this.abandonedConfig.setRemoveAbandonedTimeout(abandonedConfig.getRemoveAbandonedTimeout()); 342 this.abandonedConfig.setUseUsageTracking(abandonedConfig.getUseUsageTracking()); 343 this.abandonedConfig.setRequireFullStackTrace(abandonedConfig.getRequireFullStackTrace()); 344 } 345 } 346 347 /** 348 * Obtains a reference to the factory used to create, destroy and validate 349 * the objects used by this pool. 350 * 351 * @return the factory 352 */ 353 public PooledObjectFactory<T> getFactory() { 354 return factory; 355 } 356 357 /** 358 * Equivalent to <code>{@link #borrowObject(long) 359 * borrowObject}({@link #getMaxWaitMillis()})</code>. 360 * <p> 361 * {@inheritDoc} 362 */ 363 @Override 364 public T borrowObject() throws Exception { 365 return borrowObject(getMaxWaitMillis()); 366 } 367 368 /** 369 * Borrows an object from the pool using the specific waiting time which only 370 * applies if {@link #getBlockWhenExhausted()} is true. 371 * <p> 372 * If there is one or more idle instance available in the pool, then an 373 * idle instance will be selected based on the value of {@link #getLifo()}, 374 * activated and returned. If activation fails, or {@link #getTestOnBorrow() 375 * testOnBorrow} is set to <code>true</code> and validation fails, the 376 * instance is destroyed and the next available instance is examined. This 377 * continues until either a valid instance is returned or there are no more 378 * idle instances available. 379 * <p> 380 * If there are no idle instances available in the pool, behavior depends on 381 * the {@link #getMaxTotal() maxTotal}, (if applicable) 382 * {@link #getBlockWhenExhausted()} and the value passed in to the 383 * <code>borrowMaxWaitMillis</code> parameter. If the number of instances 384 * checked out from the pool is less than <code>maxTotal,</code> a new 385 * instance is created, activated and (if applicable) validated and returned 386 * to the caller. If validation fails, a <code>NoSuchElementException</code> 387 * is thrown. 388 * <p> 389 * If the pool is exhausted (no available idle instances and no capacity to 390 * create new ones), this method will either block (if 391 * {@link #getBlockWhenExhausted()} is true) or throw a 392 * <code>NoSuchElementException</code> (if 393 * {@link #getBlockWhenExhausted()} is false). The length of time that this 394 * method will block when {@link #getBlockWhenExhausted()} is true is 395 * determined by the value passed in to the <code>borrowMaxWaitMillis</code> 396 * parameter. 397 * <p> 398 * When the pool is exhausted, multiple calling threads may be 399 * simultaneously blocked waiting for instances to become available. A 400 * "fairness" algorithm has been implemented to ensure that threads receive 401 * available instances in request arrival order. 402 * 403 * @param borrowMaxWaitMillis The time to wait in milliseconds for an object 404 * to become available 405 * 406 * @return object instance from the pool 407 * 408 * @throws NoSuchElementException if an instance cannot be returned 409 * 410 * @throws Exception if an object instance cannot be returned due to an 411 * error 412 */ 413 public T borrowObject(final long borrowMaxWaitMillis) throws Exception { 414 assertOpen(); 415 416 final AbandonedConfig ac = this.abandonedConfig; 417 if (ac != null && ac.getRemoveAbandonedOnBorrow() && 418 (getNumIdle() < 2) && 419 (getNumActive() > getMaxTotal() - 3) ) { 420 removeAbandoned(ac); 421 } 422 423 PooledObject<T> p = null; 424 425 // Get local copy of current config so it is consistent for entire 426 // method execution 427 final boolean blockWhenExhausted = getBlockWhenExhausted(); 428 429 boolean create; 430 final long waitTime = System.currentTimeMillis(); 431 432 while (p == null) { 433 create = false; 434 p = idleObjects.pollFirst(); 435 if (p == null) { 436 p = create(); 437 if (p != null) { 438 create = true; 439 } 440 } 441 if (blockWhenExhausted) { 442 if (p == null) { 443 if (borrowMaxWaitMillis < 0) { 444 p = idleObjects.takeFirst(); 445 } else { 446 p = idleObjects.pollFirst(borrowMaxWaitMillis, 447 TimeUnit.MILLISECONDS); 448 } 449 } 450 if (p == null) { 451 throw new NoSuchElementException( 452 "Timeout waiting for idle object"); 453 } 454 } else { 455 if (p == null) { 456 throw new NoSuchElementException("Pool exhausted"); 457 } 458 } 459 if (!p.allocate()) { 460 p = null; 461 } 462 463 if (p != null) { 464 try { 465 factory.activateObject(p); 466 } catch (final Exception e) { 467 try { 468 destroy(p); 469 } catch (final Exception e1) { 470 // Ignore - activation failure is more important 471 } 472 p = null; 473 if (create) { 474 final NoSuchElementException nsee = new NoSuchElementException( 475 "Unable to activate object"); 476 nsee.initCause(e); 477 throw nsee; 478 } 479 } 480 if (p != null && (getTestOnBorrow() || create && getTestOnCreate())) { 481 boolean validate = false; 482 Throwable validationThrowable = null; 483 try { 484 validate = factory.validateObject(p); 485 } catch (final Throwable t) { 486 PoolUtils.checkRethrow(t); 487 validationThrowable = t; 488 } 489 if (!validate) { 490 try { 491 destroy(p); 492 destroyedByBorrowValidationCount.incrementAndGet(); 493 } catch (final Exception e) { 494 // Ignore - validation failure is more important 495 } 496 p = null; 497 if (create) { 498 final NoSuchElementException nsee = new NoSuchElementException( 499 "Unable to validate object"); 500 nsee.initCause(validationThrowable); 501 throw nsee; 502 } 503 } 504 } 505 } 506 } 507 508 updateStatsBorrow(p, System.currentTimeMillis() - waitTime); 509 510 return p.getObject(); 511 } 512 513 /** 514 * {@inheritDoc} 515 * <p> 516 * If {@link #getMaxIdle() maxIdle} is set to a positive value and the 517 * number of idle instances has reached this value, the returning instance 518 * is destroyed. 519 * <p> 520 * If {@link #getTestOnReturn() testOnReturn} == true, the returning 521 * instance is validated before being returned to the idle instance pool. In 522 * this case, if validation fails, the instance is destroyed. 523 * <p> 524 * Exceptions encountered destroying objects for any reason are swallowed 525 * but notified via a {@link SwallowedExceptionListener}. 526 */ 527 @Override 528 public void returnObject(final T obj) { 529 final PooledObject<T> p = allObjects.get(new IdentityWrapper<>(obj)); 530 531 if (p == null) { 532 if (!isAbandonedConfig()) { 533 throw new IllegalStateException( 534 "Returned object not currently part of this pool"); 535 } 536 return; // Object was abandoned and removed 537 } 538 539 markReturningState(p); 540 541 final long activeTime = p.getActiveTimeMillis(); 542 543 if (getTestOnReturn() && !factory.validateObject(p)) { 544 try { 545 destroy(p); 546 } catch (final Exception e) { 547 swallowException(e); 548 } 549 try { 550 ensureIdle(1, false); 551 } catch (final Exception e) { 552 swallowException(e); 553 } 554 updateStatsReturn(activeTime); 555 return; 556 } 557 558 try { 559 factory.passivateObject(p); 560 } catch (final Exception e1) { 561 swallowException(e1); 562 try { 563 destroy(p); 564 } catch (final Exception e) { 565 swallowException(e); 566 } 567 try { 568 ensureIdle(1, false); 569 } catch (final Exception e) { 570 swallowException(e); 571 } 572 updateStatsReturn(activeTime); 573 return; 574 } 575 576 if (!p.deallocate()) { 577 throw new IllegalStateException( 578 "Object has already been returned to this pool or is invalid"); 579 } 580 581 final int maxIdleSave = getMaxIdle(); 582 if (isClosed() || maxIdleSave > -1 && maxIdleSave <= idleObjects.size()) { 583 try { 584 destroy(p); 585 } catch (final Exception e) { 586 swallowException(e); 587 } 588 } else { 589 if (getLifo()) { 590 idleObjects.addFirst(p); 591 } else { 592 idleObjects.addLast(p); 593 } 594 if (isClosed()) { 595 // Pool closed while object was being added to idle objects. 596 // Make sure the returned object is destroyed rather than left 597 // in the idle object pool (which would effectively be a leak) 598 clear(); 599 } 600 } 601 updateStatsReturn(activeTime); 602 } 603 604 /** 605 * {@inheritDoc} 606 * <p> 607 * Activation of this method decrements the active count and attempts to 608 * destroy the instance. 609 * 610 * @throws Exception if an exception occurs destroying the 611 * object 612 * @throws IllegalStateException if obj does not belong to this pool 613 */ 614 @Override 615 public void invalidateObject(final T obj) throws Exception { 616 final PooledObject<T> p = allObjects.get(new IdentityWrapper<>(obj)); 617 if (p == null) { 618 if (isAbandonedConfig()) { 619 return; 620 } 621 throw new IllegalStateException( 622 "Invalidated object not currently part of this pool"); 623 } 624 synchronized (p) { 625 if (p.getState() != PooledObjectState.INVALID) { 626 destroy(p); 627 } 628 } 629 ensureIdle(1, false); 630 } 631 632 /** 633 * Clears any objects sitting idle in the pool by removing them from the 634 * idle instance pool and then invoking the configured 635 * {@link PooledObjectFactory#destroyObject(PooledObject)} method on each 636 * idle instance. 637 * <p> 638 * Implementation notes: 639 * <ul> 640 * <li>This method does not destroy or effect in any way instances that are 641 * checked out of the pool when it is invoked.</li> 642 * <li>Invoking this method does not prevent objects being returned to the 643 * idle instance pool, even during its execution. Additional instances may 644 * be returned while removed items are being destroyed.</li> 645 * <li>Exceptions encountered destroying idle instances are swallowed 646 * but notified via a {@link SwallowedExceptionListener}.</li> 647 * </ul> 648 */ 649 @Override 650 public void clear() { 651 PooledObject<T> p = idleObjects.poll(); 652 653 while (p != null) { 654 try { 655 destroy(p); 656 } catch (final Exception e) { 657 swallowException(e); 658 } 659 p = idleObjects.poll(); 660 } 661 } 662 663 @Override 664 public int getNumActive() { 665 return allObjects.size() - idleObjects.size(); 666 } 667 668 @Override 669 public int getNumIdle() { 670 return idleObjects.size(); 671 } 672 673 /** 674 * Closes the pool. Once the pool is closed, {@link #borrowObject()} will 675 * fail with IllegalStateException, but {@link #returnObject(Object)} and 676 * {@link #invalidateObject(Object)} will continue to work, with returned 677 * objects destroyed on return. 678 * <p> 679 * Destroys idle instances in the pool by invoking {@link #clear()}. 680 */ 681 @Override 682 public void close() { 683 if (isClosed()) { 684 return; 685 } 686 687 synchronized (closeLock) { 688 if (isClosed()) { 689 return; 690 } 691 692 // Stop the evictor before the pool is closed since evict() calls 693 // assertOpen() 694 startEvictor(-1L); 695 696 closed = true; 697 // This clear removes any idle objects 698 clear(); 699 700 jmxUnregister(); 701 702 // Release any threads that were waiting for an object 703 idleObjects.interuptTakeWaiters(); 704 } 705 } 706 707 /** 708 * {@inheritDoc} 709 * <p> 710 * Successive activations of this method examine objects in sequence, 711 * cycling through objects in oldest-to-youngest order. 712 */ 713 @Override 714 public void evict() throws Exception { 715 assertOpen(); 716 717 if (idleObjects.size() > 0) { 718 719 PooledObject<T> underTest = null; 720 final EvictionPolicy<T> evictionPolicy = getEvictionPolicy(); 721 722 synchronized (evictionLock) { 723 final EvictionConfig evictionConfig = new EvictionConfig( 724 getMinEvictableIdleTimeMillis(), 725 getSoftMinEvictableIdleTimeMillis(), 726 getMinIdle()); 727 728 final boolean testWhileIdle = getTestWhileIdle(); 729 730 for (int i = 0, m = getNumTests(); i < m; i++) { 731 if (evictionIterator == null || !evictionIterator.hasNext()) { 732 evictionIterator = new EvictionIterator(idleObjects); 733 } 734 if (!evictionIterator.hasNext()) { 735 // Pool exhausted, nothing to do here 736 return; 737 } 738 739 try { 740 underTest = evictionIterator.next(); 741 } catch (final NoSuchElementException nsee) { 742 // Object was borrowed in another thread 743 // Don't count this as an eviction test so reduce i; 744 i--; 745 evictionIterator = null; 746 continue; 747 } 748 749 if (!underTest.startEvictionTest()) { 750 // Object was borrowed in another thread 751 // Don't count this as an eviction test so reduce i; 752 i--; 753 continue; 754 } 755 756 // User provided eviction policy could throw all sorts of 757 // crazy exceptions. Protect against such an exception 758 // killing the eviction thread. 759 boolean evict; 760 try { 761 evict = evictionPolicy.evict(evictionConfig, underTest, 762 idleObjects.size()); 763 } catch (final Throwable t) { 764 // Slightly convoluted as SwallowedExceptionListener 765 // uses Exception rather than Throwable 766 PoolUtils.checkRethrow(t); 767 swallowException(new Exception(t)); 768 // Don't evict on error conditions 769 evict = false; 770 } 771 772 if (evict) { 773 destroy(underTest); 774 destroyedByEvictorCount.incrementAndGet(); 775 } else { 776 if (testWhileIdle) { 777 boolean active = false; 778 try { 779 factory.activateObject(underTest); 780 active = true; 781 } catch (final Exception e) { 782 destroy(underTest); 783 destroyedByEvictorCount.incrementAndGet(); 784 } 785 if (active) { 786 if (!factory.validateObject(underTest)) { 787 destroy(underTest); 788 destroyedByEvictorCount.incrementAndGet(); 789 } else { 790 try { 791 factory.passivateObject(underTest); 792 } catch (final Exception e) { 793 destroy(underTest); 794 destroyedByEvictorCount.incrementAndGet(); 795 } 796 } 797 } 798 } 799 if (!underTest.endEvictionTest(idleObjects)) { 800 // TODO - May need to add code here once additional 801 // states are used 802 } 803 } 804 } 805 } 806 } 807 final AbandonedConfig ac = this.abandonedConfig; 808 if (ac != null && ac.getRemoveAbandonedOnMaintenance()) { 809 removeAbandoned(ac); 810 } 811 } 812 813 /** 814 * Tries to ensure that {@link #getMinIdle()} idle instances are available 815 * in the pool. 816 * 817 * @throws Exception If the associated factory throws an exception 818 * @since 2.4 819 */ 820 public void preparePool() throws Exception { 821 if (getMinIdle() < 1) { 822 return; 823 } 824 ensureMinIdle(); 825 } 826 827 /** 828 * Attempts to create a new wrapped pooled object. 829 * <p> 830 * If there are {@link #getMaxTotal()} objects already in circulation 831 * or in process of being created, this method returns null. 832 * 833 * @return The new wrapped pooled object 834 * 835 * @throws Exception if the object factory's {@code makeObject} fails 836 */ 837 private PooledObject<T> create() throws Exception { 838 int localMaxTotal = getMaxTotal(); 839 // This simplifies the code later in this method 840 if (localMaxTotal < 0) { 841 localMaxTotal = Integer.MAX_VALUE; 842 } 843 844 // Flag that indicates if create should: 845 // - TRUE: call the factory to create an object 846 // - FALSE: return null 847 // - null: loop and re-test the condition that determines whether to 848 // call the factory 849 Boolean create = null; 850 while (create == null) { 851 synchronized (makeObjectCountLock) { 852 final long newCreateCount = createCount.incrementAndGet(); 853 if (newCreateCount > localMaxTotal) { 854 // The pool is currently at capacity or in the process of 855 // making enough new objects to take it to capacity. 856 createCount.decrementAndGet(); 857 if (makeObjectCount == 0) { 858 // There are no makeObject() calls in progress so the 859 // pool is at capacity. Do not attempt to create a new 860 // object. Return and wait for an object to be returned 861 create = Boolean.FALSE; 862 } else { 863 // There are makeObject() calls in progress that might 864 // bring the pool to capacity. Those calls might also 865 // fail so wait until they complete and then re-test if 866 // the pool is at capacity or not. 867 makeObjectCountLock.wait(); 868 } 869 } else { 870 // The pool is not at capacity. Create a new object. 871 makeObjectCount++; 872 create = Boolean.TRUE; 873 } 874 } 875 } 876 877 if (!create.booleanValue()) { 878 return null; 879 } 880 881 final PooledObject<T> p; 882 try { 883 p = factory.makeObject(); 884 } catch (final Throwable e) { 885 createCount.decrementAndGet(); 886 throw e; 887 } finally { 888 synchronized (makeObjectCountLock) { 889 makeObjectCount--; 890 makeObjectCountLock.notifyAll(); 891 } 892 } 893 894 final AbandonedConfig ac = this.abandonedConfig; 895 if (ac != null && ac.getLogAbandoned()) { 896 p.setLogAbandoned(true); 897 // TODO: in 3.0, this can use the method defined on PooledObject 898 if (p instanceof DefaultPooledObject<?>) { 899 ((DefaultPooledObject<T>) p).setRequireFullStackTrace(ac.getRequireFullStackTrace()); 900 } 901 } 902 903 createdCount.incrementAndGet(); 904 allObjects.put(new IdentityWrapper<>(p.getObject()), p); 905 return p; 906 } 907 908 /** 909 * Destroys a wrapped pooled object. 910 * 911 * @param toDestroy The wrapped pooled object to destroy 912 * 913 * @throws Exception If the factory fails to destroy the pooled object 914 * cleanly 915 */ 916 private void destroy(final PooledObject<T> toDestroy) throws Exception { 917 toDestroy.invalidate(); 918 idleObjects.remove(toDestroy); 919 allObjects.remove(new IdentityWrapper<>(toDestroy.getObject())); 920 try { 921 factory.destroyObject(toDestroy); 922 } finally { 923 destroyedCount.incrementAndGet(); 924 createCount.decrementAndGet(); 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}