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