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