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: 1627011 $ 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(obj); 538 539 if (!isAbandonedConfig()) { 540 if (p == null) { 541 throw new IllegalStateException( 542 "Returned object not currently part of this pool"); 543 } 544 } else { 545 if (p == null) { 546 return; // Object was abandoned and removed 547 } else { 548 // Make sure object is not being reclaimed 549 synchronized(p) { 550 final PooledObjectState state = p.getState(); 551 if (state != PooledObjectState.ALLOCATED) { 552 throw new IllegalStateException( 553 "Object has already been returned to this pool or is invalid"); 554 } else { 555 p.markReturning(); // Keep from being marked abandoned 556 } 557 } 558 } 559 } 560 561 long activeTime = p.getActiveTimeMillis(); 562 563 if (getTestOnReturn()) { 564 if (!factory.validateObject(p)) { 565 try { 566 destroy(p); 567 } catch (Exception e) { 568 swallowException(e); 569 } 570 try { 571 ensureIdle(1, false); 572 } catch (Exception e) { 573 swallowException(e); 574 } 575 updateStatsReturn(activeTime); 576 return; 577 } 578 } 579 580 try { 581 factory.passivateObject(p); 582 } catch (Exception e1) { 583 swallowException(e1); 584 try { 585 destroy(p); 586 } catch (Exception e) { 587 swallowException(e); 588 } 589 try { 590 ensureIdle(1, false); 591 } catch (Exception e) { 592 swallowException(e); 593 } 594 updateStatsReturn(activeTime); 595 return; 596 } 597 598 if (!p.deallocate()) { 599 throw new IllegalStateException( 600 "Object has already been returned to this pool or is invalid"); 601 } 602 603 int maxIdleSave = getMaxIdle(); 604 if (isClosed() || maxIdleSave > -1 && maxIdleSave <= idleObjects.size()) { 605 try { 606 destroy(p); 607 } catch (Exception e) { 608 swallowException(e); 609 } 610 } else { 611 if (getLifo()) { 612 idleObjects.addFirst(p); 613 } else { 614 idleObjects.addLast(p); 615 } 616 if (isClosed()) { 617 // Pool closed while object was being added to idle objects. 618 // Make sure the returned object is destroyed rather than left 619 // in the idle object pool (which would effectively be a leak) 620 clear(); 621 } 622 } 623 updateStatsReturn(activeTime); 624 } 625 626 /** 627 * {@inheritDoc} 628 * <p> 629 * Activation of this method decrements the active count and attempts to 630 * destroy the instance. 631 * 632 * @throws Exception if an exception occurs destroying the 633 * object 634 * @throws IllegalStateException if obj does not belong to this pool 635 */ 636 @Override 637 public void invalidateObject(T obj) throws Exception { 638 PooledObject<T> p = allObjects.get(obj); 639 if (p == null) { 640 if (isAbandonedConfig()) { 641 return; 642 } else { 643 throw new IllegalStateException( 644 "Invalidated object not currently part of this pool"); 645 } 646 } 647 synchronized (p) { 648 if (p.getState() != PooledObjectState.INVALID) { 649 destroy(p); 650 } 651 } 652 ensureIdle(1, false); 653 } 654 655 /** 656 * Clears any objects sitting idle in the pool by removing them from the 657 * idle instance pool and then invoking the configured 658 * {@link PooledObjectFactory#destroyObject(PooledObject)} method on each 659 * idle instance. 660 * <p> 661 * Implementation notes: 662 * <ul> 663 * <li>This method does not destroy or effect in any way instances that are 664 * checked out of the pool when it is invoked.</li> 665 * <li>Invoking this method does not prevent objects being returned to the 666 * idle instance pool, even during its execution. Additional instances may 667 * be returned while removed items are being destroyed.</li> 668 * <li>Exceptions encountered destroying idle instances are swallowed 669 * but notified via a {@link SwallowedExceptionListener}.</li> 670 * </ul> 671 */ 672 @Override 673 public void clear() { 674 PooledObject<T> p = idleObjects.poll(); 675 676 while (p != null) { 677 try { 678 destroy(p); 679 } catch (Exception e) { 680 swallowException(e); 681 } 682 p = idleObjects.poll(); 683 } 684 } 685 686 @Override 687 public int getNumActive() { 688 return allObjects.size() - idleObjects.size(); 689 } 690 691 @Override 692 public int getNumIdle() { 693 return idleObjects.size(); 694 } 695 696 /** 697 * Closes the pool. Once the pool is closed, {@link #borrowObject()} will 698 * fail with IllegalStateException, but {@link #returnObject(Object)} and 699 * {@link #invalidateObject(Object)} will continue to work, with returned 700 * objects destroyed on return. 701 * <p> 702 * Destroys idle instances in the pool by invoking {@link #clear()}. 703 */ 704 @Override 705 public void close() { 706 if (isClosed()) { 707 return; 708 } 709 710 synchronized (closeLock) { 711 if (isClosed()) { 712 return; 713 } 714 715 // Stop the evictor before the pool is closed since evict() calls 716 // assertOpen() 717 startEvictor(-1L); 718 719 closed = true; 720 // This clear removes any idle objects 721 clear(); 722 723 jmxUnregister(); 724 725 // Release any threads that were waiting for an object 726 idleObjects.interuptTakeWaiters(); 727 } 728 } 729 730 /** 731 * {@inheritDoc} 732 * <p> 733 * Successive activations of this method examine objects in sequence, 734 * cycling through objects in oldest-to-youngest order. 735 */ 736 @Override 737 public void evict() throws Exception { 738 assertOpen(); 739 740 if (idleObjects.size() > 0) { 741 742 PooledObject<T> underTest = null; 743 EvictionPolicy<T> evictionPolicy = getEvictionPolicy(); 744 745 synchronized (evictionLock) { 746 EvictionConfig evictionConfig = new EvictionConfig( 747 getMinEvictableIdleTimeMillis(), 748 getSoftMinEvictableIdleTimeMillis(), 749 getMinIdle()); 750 751 boolean testWhileIdle = getTestWhileIdle(); 752 753 for (int i = 0, m = getNumTests(); i < m; i++) { 754 if (evictionIterator == null || !evictionIterator.hasNext()) { 755 if (getLifo()) { 756 evictionIterator = idleObjects.descendingIterator(); 757 } else { 758 evictionIterator = idleObjects.iterator(); 759 } 760 } 761 if (!evictionIterator.hasNext()) { 762 // Pool exhausted, nothing to do here 763 return; 764 } 765 766 try { 767 underTest = evictionIterator.next(); 768 } catch (NoSuchElementException nsee) { 769 // Object was borrowed in another thread 770 // Don't count this as an eviction test so reduce i; 771 i--; 772 evictionIterator = null; 773 continue; 774 } 775 776 if (!underTest.startEvictionTest()) { 777 // Object was borrowed in another thread 778 // Don't count this as an eviction test so reduce i; 779 i--; 780 continue; 781 } 782 783 // User provided eviction policy could throw all sorts of 784 // crazy exceptions. Protect against such an exception 785 // killing the eviction thread. 786 boolean evict; 787 try { 788 evict = evictionPolicy.evict(evictionConfig, underTest, 789 idleObjects.size()); 790 } catch (Throwable t) { 791 // Slightly convoluted as SwallowedExceptionListener 792 // uses Exception rather than Throwable 793 PoolUtils.checkRethrow(t); 794 swallowException(new Exception(t)); 795 // Don't evict on error conditions 796 evict = false; 797 } 798 799 if (evict) { 800 destroy(underTest); 801 destroyedByEvictorCount.incrementAndGet(); 802 } else { 803 if (testWhileIdle) { 804 boolean active = false; 805 try { 806 factory.activateObject(underTest); 807 active = true; 808 } catch (Exception e) { 809 destroy(underTest); 810 destroyedByEvictorCount.incrementAndGet(); 811 } 812 if (active) { 813 if (!factory.validateObject(underTest)) { 814 destroy(underTest); 815 destroyedByEvictorCount.incrementAndGet(); 816 } else { 817 try { 818 factory.passivateObject(underTest); 819 } catch (Exception e) { 820 destroy(underTest); 821 destroyedByEvictorCount.incrementAndGet(); 822 } 823 } 824 } 825 } 826 if (!underTest.endEvictionTest(idleObjects)) { 827 // TODO - May need to add code here once additional 828 // states are used 829 } 830 } 831 } 832 } 833 } 834 AbandonedConfig ac = this.abandonedConfig; 835 if (ac != null && ac.getRemoveAbandonedOnMaintenance()) { 836 removeAbandoned(ac); 837 } 838 } 839 840 /** 841 * Attempts to create a new wrapped pooled object. 842 * <p> 843 * If there are {@link #getMaxTotal()} objects already in circulation 844 * or in process of being created, this method returns null. 845 * 846 * @return The new wrapped pooled object 847 * 848 * @throws Exception if the object factory's {@code makeObject} fails 849 */ 850 private PooledObject<T> create() throws Exception { 851 int localMaxTotal = getMaxTotal(); 852 long newCreateCount = createCount.incrementAndGet(); 853 if (localMaxTotal > -1 && newCreateCount > localMaxTotal || 854 newCreateCount > Integer.MAX_VALUE) { 855 createCount.decrementAndGet(); 856 return null; 857 } 858 859 final PooledObject<T> p; 860 try { 861 p = factory.makeObject(); 862 } catch (Exception e) { 863 createCount.decrementAndGet(); 864 throw e; 865 } 866 867 AbandonedConfig ac = this.abandonedConfig; 868 if (ac != null && ac.getLogAbandoned()) { 869 p.setLogAbandoned(true); 870 } 871 872 createdCount.incrementAndGet(); 873 allObjects.put(p.getObject(), p); 874 return p; 875 } 876 877 /** 878 * Destroys a wrapped pooled object. 879 * 880 * @param toDestory The wrapped pooled object to destroy 881 * 882 * @throws Exception If the factory fails to destroy the pooled object 883 * cleanly 884 */ 885 private void destroy(PooledObject<T> toDestory) throws Exception { 886 toDestory.invalidate(); 887 idleObjects.remove(toDestory); 888 allObjects.remove(toDestory.getObject()); 889 try { 890 factory.destroyObject(toDestory); 891 } finally { 892 destroyedCount.incrementAndGet(); 893 createCount.decrementAndGet(); 894 } 895 } 896 897 @Override 898 void ensureMinIdle() throws Exception { 899 ensureIdle(getMinIdle(), true); 900 } 901 902 /** 903 * Tries to ensure that {@code idleCount} idle instances exist in the pool. 904 * <p> 905 * Creates and adds idle instances until either {@link #getNumIdle()} reaches {@code idleCount} 906 * or the total number of objects (idle, checked out, or being created) reaches 907 * {@link #getMaxTotal()}. If {@code always} is false, no instances are created unless 908 * there are threads waiting to check out instances from the pool. 909 * 910 * @param idleCount the number of idle instances desired 911 * @param always true means create instances even if the pool has no threads waiting 912 * @throws Exception if the factory's makeObject throws 913 */ 914 private void ensureIdle(int idleCount, boolean always) throws Exception { 915 if (idleCount < 1 || isClosed() || (!always && !idleObjects.hasTakeWaiters())) { 916 return; 917 } 918 919 while (idleObjects.size() < idleCount) { 920 PooledObject<T> p = create(); 921 if (p == null) { 922 // Can't create objects, no reason to think another call to 923 // create will work. Give up. 924 break; 925 } 926 if (getLifo()) { 927 idleObjects.addFirst(p); 928 } else { 929 idleObjects.addLast(p); 930 } 931 } 932 if (isClosed()) { 933 // Pool closed while object was being added to idle objects. 934 // Make sure the returned object is destroyed rather than left 935 // in the idle object pool (which would effectively be a leak) 936 clear(); 937 } 938 } 939 940 /** 941 * Create an object, and place it into the pool. addObject() is useful for 942 * "pre-loading" a pool with idle objects. 943 */ 944 @Override 945 public void addObject() throws Exception { 946 assertOpen(); 947 if (factory == null) { 948 throw new IllegalStateException( 949 "Cannot add objects without a factory."); 950 } 951 PooledObject<T> p = create(); 952 addIdleObject(p); 953 } 954 955 /** 956 * Add the provided wrapped pooled object to the set of idle objects for 957 * this pool. The object must already be part of the pool. 958 * 959 * @param p The object to make idle 960 * 961 * @throws Exception If the factory fails to passivate the object 962 */ 963 private void addIdleObject(PooledObject<T> p) throws Exception { 964 if (p != null) { 965 factory.passivateObject(p); 966 if (getLifo()) { 967 idleObjects.addFirst(p); 968 } else { 969 idleObjects.addLast(p); 970 } 971 } 972 } 973 974 /** 975 * Calculate the number of objects to test in a run of the idle object 976 * evictor. 977 * 978 * @return The number of objects to test for validity 979 */ 980 private int getNumTests() { 981 int numTestsPerEvictionRun = getNumTestsPerEvictionRun(); 982 if (numTestsPerEvictionRun >= 0) { 983 return Math.min(numTestsPerEvictionRun, idleObjects.size()); 984 } else { 985 return (int) (Math.ceil(idleObjects.size() / 986 Math.abs((double) numTestsPerEvictionRun))); 987 } 988 } 989 990 /** 991 * Recover abandoned objects which have been checked out but 992 * not used since longer than the removeAbandonedTimeout. 993 * 994 * @param ac The configuration to use to identify abandoned objects 995 */ 996 private void removeAbandoned(AbandonedConfig ac) { 997 // Generate a list of abandoned objects to remove 998 final long now = System.currentTimeMillis(); 999 final long timeout = 1000 now - (ac.getRemoveAbandonedTimeout() * 1000L); 1001 ArrayList<PooledObject<T>> remove = new ArrayList<PooledObject<T>>(); 1002 Iterator<PooledObject<T>> it = allObjects.values().iterator(); 1003 while (it.hasNext()) { 1004 PooledObject<T> pooledObject = it.next(); 1005 synchronized (pooledObject) { 1006 if (pooledObject.getState() == PooledObjectState.ALLOCATED && 1007 pooledObject.getLastUsedTime() <= timeout) { 1008 pooledObject.markAbandoned(); 1009 remove.add(pooledObject); 1010 } 1011 } 1012 } 1013 1014 // Now remove the abandoned objects 1015 Iterator<PooledObject<T>> itr = remove.iterator(); 1016 while (itr.hasNext()) { 1017 PooledObject<T> pooledObject = itr.next(); 1018 if (ac.getLogAbandoned()) { 1019 pooledObject.printStackTrace(ac.getLogWriter()); 1020 } 1021 try { 1022 invalidateObject(pooledObject.getObject()); 1023 } catch (Exception e) { 1024 e.printStackTrace(); 1025 } 1026 } 1027 } 1028 1029 1030 //--- Usage tracking support ----------------------------------------------- 1031 1032 @Override 1033 public void use(T pooledObject) { 1034 AbandonedConfig ac = this.abandonedConfig; 1035 if (ac != null && ac.getUseUsageTracking()) { 1036 PooledObject<T> wrapper = allObjects.get(pooledObject); 1037 wrapper.use(); 1038 } 1039 } 1040 1041 1042 //--- JMX support ---------------------------------------------------------- 1043 1044 private volatile String factoryType = null; 1045 1046 /** 1047 * Return an estimate of the number of threads currently blocked waiting for 1048 * an object from the pool. This is intended for monitoring only, not for 1049 * synchronization control. 1050 * 1051 * @return The estimate of the number of threads currently blocked waiting 1052 * for an object from the pool 1053 */ 1054 @Override 1055 public int getNumWaiters() { 1056 if (getBlockWhenExhausted()) { 1057 return idleObjects.getTakeQueueLength(); 1058 } else { 1059 return 0; 1060 } 1061 } 1062 1063 /** 1064 * Return the type - including the specific type rather than the generic - 1065 * of the factory. 1066 * 1067 * @return A string representation of the factory type 1068 */ 1069 @Override 1070 public String getFactoryType() { 1071 // Not thread safe. Accept that there may be multiple evaluations. 1072 if (factoryType == null) { 1073 StringBuilder result = new StringBuilder(); 1074 result.append(factory.getClass().getName()); 1075 result.append('<'); 1076 Class<?> pooledObjectType = 1077 PoolImplUtils.getFactoryType(factory.getClass()); 1078 result.append(pooledObjectType.getName()); 1079 result.append('>'); 1080 factoryType = result.toString(); 1081 } 1082 return factoryType; 1083 } 1084 1085 /** 1086 * Provides information on all the objects in the pool, both idle (waiting 1087 * to be borrowed) and active (currently borrowed). 1088 * <p> 1089 * Note: This is named listAllObjects so it is presented as an operation via 1090 * JMX. That means it won't be invoked unless the explicitly requested 1091 * whereas all attributes will be automatically requested when viewing the 1092 * attributes for an object in a tool like JConsole. 1093 * 1094 * @return Information grouped on all the objects in the pool 1095 */ 1096 @Override 1097 public Set<DefaultPooledObjectInfo> listAllObjects() { 1098 Set<DefaultPooledObjectInfo> result = 1099 new HashSet<DefaultPooledObjectInfo>(allObjects.size()); 1100 for (PooledObject<T> p : allObjects.values()) { 1101 result.add(new DefaultPooledObjectInfo(p)); 1102 } 1103 return result; 1104 } 1105 1106 // --- configuration attributes -------------------------------------------- 1107 1108 private volatile int maxIdle = GenericObjectPoolConfig.DEFAULT_MAX_IDLE; 1109 private volatile int minIdle = GenericObjectPoolConfig.DEFAULT_MIN_IDLE; 1110 private final PooledObjectFactory<T> factory; 1111 1112 1113 // --- internal attributes ------------------------------------------------- 1114 1115 /* 1116 * All of the objects currently associated with this pool in any state. It 1117 * excludes objects that have been destroyed. The size of 1118 * {@link #allObjects} will always be less than or equal to {@link 1119 * #_maxActive}. Map keys are pooled objects, values are the PooledObject 1120 * wrappers used internally by the pool. 1121 */ 1122 private final Map<T, PooledObject<T>> allObjects = 1123 new ConcurrentHashMap<T, PooledObject<T>>(); 1124 /* 1125 * The combined count of the currently created objects and those in the 1126 * process of being created. Under load, it may exceed {@link #_maxActive} 1127 * if multiple threads try and create a new object at the same time but 1128 * {@link #create()} will ensure that there are never more than 1129 * {@link #_maxActive} objects created at any one time. 1130 */ 1131 private final AtomicLong createCount = new AtomicLong(0); 1132 private final LinkedBlockingDeque<PooledObject<T>> idleObjects; 1133 1134 // JMX specific attributes 1135 private static final String ONAME_BASE = 1136 "org.apache.commons.pool2:type=GenericObjectPool,name="; 1137 1138 // Additional configuration properties for abandoned object tracking 1139 private volatile AbandonedConfig abandonedConfig = null; 1140}