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