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.io.PrintWriter; 020import java.io.StringWriter; 021import java.io.Writer; 022import java.lang.management.ManagementFactory; 023import java.lang.ref.WeakReference; 024import java.lang.reflect.InvocationTargetException; 025import java.time.Duration; 026import java.time.Instant; 027import java.util.ArrayList; 028import java.util.Arrays; 029import java.util.Deque; 030import java.util.Iterator; 031import java.util.List; 032import java.util.Map; 033import java.util.TimerTask; 034import java.util.concurrent.ScheduledFuture; 035import java.util.concurrent.atomic.AtomicLong; 036import java.util.concurrent.atomic.AtomicReference; 037import java.util.stream.Collectors; 038 039import javax.management.InstanceAlreadyExistsException; 040import javax.management.InstanceNotFoundException; 041import javax.management.MBeanRegistrationException; 042import javax.management.MBeanServer; 043import javax.management.MalformedObjectNameException; 044import javax.management.NotCompliantMBeanException; 045import javax.management.ObjectName; 046 047import org.apache.commons.pool2.BaseObject; 048import org.apache.commons.pool2.PooledObject; 049import org.apache.commons.pool2.PooledObjectState; 050import org.apache.commons.pool2.SwallowedExceptionListener; 051 052/** 053 * Base class that provides common functionality for {@link GenericObjectPool} 054 * and {@link GenericKeyedObjectPool}. The primary reason this class exists is 055 * reduce code duplication between the two pool implementations. 056 * 057 * @param <T> Type of element pooled in this pool. 058 * 059 * This class is intended to be thread-safe. 060 * 061 * @since 2.0 062 */ 063public abstract class BaseGenericObjectPool<T> extends BaseObject { 064 065 /** 066 * The idle object eviction iterator. Holds a reference to the idle objects. 067 */ 068 class EvictionIterator implements Iterator<PooledObject<T>> { 069 070 private final Deque<PooledObject<T>> idleObjects; 071 private final Iterator<PooledObject<T>> idleObjectIterator; 072 073 /** 074 * Constructs an EvictionIterator for the provided idle instance deque. 075 * @param idleObjects underlying deque. 076 */ 077 EvictionIterator(final Deque<PooledObject<T>> idleObjects) { 078 this.idleObjects = idleObjects; 079 080 if (getLifo()) { 081 idleObjectIterator = idleObjects.descendingIterator(); 082 } else { 083 idleObjectIterator = idleObjects.iterator(); 084 } 085 } 086 087 /** 088 * Gets the idle object deque referenced by this iterator. 089 * @return the idle object deque 090 */ 091 public Deque<PooledObject<T>> getIdleObjects() { 092 return idleObjects; 093 } 094 095 /** {@inheritDoc} */ 096 @Override 097 public boolean hasNext() { 098 return idleObjectIterator.hasNext(); 099 } 100 101 /** {@inheritDoc} */ 102 @Override 103 public PooledObject<T> next() { 104 return idleObjectIterator.next(); 105 } 106 107 /** {@inheritDoc} */ 108 @Override 109 public void remove() { 110 idleObjectIterator.remove(); 111 } 112 113 } 114 115 /** 116 * The idle object evictor {@link TimerTask}. 117 * 118 * @see GenericKeyedObjectPool#setTimeBetweenEvictionRunsMillis 119 */ 120 class Evictor implements Runnable { 121 122 private ScheduledFuture<?> scheduledFuture; 123 124 /** 125 * Cancels the scheduled future. 126 */ 127 void cancel() { 128 scheduledFuture.cancel(false); 129 } 130 131 132 /** 133 * Run pool maintenance. Evict objects qualifying for eviction and then 134 * ensure that the minimum number of idle instances are available. 135 * Since the Timer that invokes Evictors is shared for all Pools but 136 * pools may exist in different class loaders, the Evictor ensures that 137 * any actions taken are under the class loader of the factory 138 * associated with the pool. 139 */ 140 @Override 141 public void run() { 142 final ClassLoader savedClassLoader = 143 Thread.currentThread().getContextClassLoader(); 144 try { 145 if (factoryClassLoader != null) { 146 // Set the class loader for the factory 147 final ClassLoader cl = factoryClassLoader.get(); 148 if (cl == null) { 149 // The pool has been dereferenced and the class loader 150 // GC'd. Cancel this timer so the pool can be GC'd as 151 // well. 152 cancel(); 153 return; 154 } 155 Thread.currentThread().setContextClassLoader(cl); 156 } 157 158 // Evict from the pool 159 try { 160 evict(); 161 } catch(final Exception e) { 162 swallowException(e); 163 } catch(final OutOfMemoryError oome) { 164 // Log problem but give evictor thread a chance to continue 165 // in case error is recoverable 166 oome.printStackTrace(System.err); 167 } 168 // Re-create idle instances. 169 try { 170 ensureMinIdle(); 171 } catch (final Exception e) { 172 swallowException(e); 173 } 174 } finally { 175 // Restore the previous CCL 176 Thread.currentThread().setContextClassLoader(savedClassLoader); 177 } 178 } 179 180 181 /** 182 * Sets the scheduled future. 183 * 184 * @param scheduledFuture the scheduled future. 185 */ 186 void setScheduledFuture(final ScheduledFuture<?> scheduledFuture) { 187 this.scheduledFuture = scheduledFuture; 188 } 189 190 } 191 192 /** 193 * Wrapper for objects under management by the pool. 194 * 195 * GenericObjectPool and GenericKeyedObjectPool maintain references to all 196 * objects under management using maps keyed on the objects. This wrapper 197 * class ensures that objects can work as hash keys. 198 * 199 * @param <T> type of objects in the pool 200 */ 201 static class IdentityWrapper<T> { 202 /** Wrapped object */ 203 private final T instance; 204 205 /** 206 * Constructs a wrapper for an instance. 207 * 208 * @param instance object to wrap 209 */ 210 public IdentityWrapper(final T instance) { 211 this.instance = instance; 212 } 213 214 @Override 215 @SuppressWarnings("rawtypes") 216 public boolean equals(final Object other) { 217 return other instanceof IdentityWrapper && ((IdentityWrapper) other).instance == instance; 218 } 219 220 /** 221 * @return the wrapped object 222 */ 223 public T getObject() { 224 return instance; 225 } 226 227 @Override 228 public int hashCode() { 229 return System.identityHashCode(instance); 230 } 231 232 @Override 233 public String toString() { 234 final StringBuilder builder = new StringBuilder(); 235 builder.append("IdentityWrapper [instance="); 236 builder.append(instance); 237 builder.append("]"); 238 return builder.toString(); 239 } 240 } 241 242 /** 243 * Maintains a cache of values for a single metric and reports 244 * statistics on the cached values. 245 */ 246 private class StatsStore { 247 248 private static final int NULL = -1; 249 private final AtomicLong[] values; 250 private final int size; 251 private int index; 252 253 /** 254 * Constructs a StatsStore with the given cache size. 255 * 256 * @param size number of values to maintain in the cache. 257 */ 258 StatsStore(final int size) { 259 this.size = size; 260 values = new AtomicLong[size]; 261 for (int i = 0; i < size; i++) { 262 values[i] = new AtomicLong(NULL); 263 } 264 } 265 266 void add(final Duration value) { 267 add(value.toMillis()); 268 } 269 270 /** 271 * Adds a value to the cache. If the cache is full, one of the 272 * existing values is replaced by the new value. 273 * 274 * @param value new value to add to the cache. 275 */ 276 synchronized void add(final long value) { 277 values[index].set(value); 278 index++; 279 if (index == size) { 280 index = 0; 281 } 282 } 283 284 /** 285 * Gets the current values as a List. 286 * 287 * @return the current values as a List. 288 */ 289 synchronized List<AtomicLong> getCurrentValues() { 290 return Arrays.stream(values, 0, index).collect(Collectors.toList()); 291 } 292 293 /** 294 * Gets the mean of the cached values. 295 * 296 * @return the mean of the cache, truncated to long 297 */ 298 public long getMean() { 299 double result = 0; 300 int counter = 0; 301 for (int i = 0; i < size; i++) { 302 final long value = values[i].get(); 303 if (value != NULL) { 304 counter++; 305 result = result * ((counter - 1) / (double) counter) + value / (double) counter; 306 } 307 } 308 return (long) result; 309 } 310 311 @Override 312 public String toString() { 313 final StringBuilder builder = new StringBuilder(); 314 builder.append("StatsStore ["); 315 // Only append what's been filled in. 316 builder.append(getCurrentValues()); 317 builder.append("], size="); 318 builder.append(size); 319 builder.append(", index="); 320 builder.append(index); 321 builder.append("]"); 322 return builder.toString(); 323 } 324 325 } 326 327 // Constants 328 /** 329 * The size of the caches used to store historical data for some attributes 330 * so that rolling means may be calculated. 331 */ 332 public static final int MEAN_TIMING_STATS_CACHE_SIZE = 100; 333 private static final String EVICTION_POLICY_TYPE_NAME = EvictionPolicy.class.getName(); 334 private static final Duration DEFAULT_REMOVE_ABANDONED_TIMEOUT = Duration.ofSeconds(Integer.MAX_VALUE); 335 // Configuration attributes 336 private volatile int maxTotal = GenericKeyedObjectPoolConfig.DEFAULT_MAX_TOTAL; 337 private volatile boolean blockWhenExhausted = BaseObjectPoolConfig.DEFAULT_BLOCK_WHEN_EXHAUSTED; 338 private volatile Duration maxWaitDuration = BaseObjectPoolConfig.DEFAULT_MAX_WAIT; 339 private volatile boolean lifo = BaseObjectPoolConfig.DEFAULT_LIFO; 340 private final boolean fairness; 341 private volatile boolean testOnCreate = BaseObjectPoolConfig.DEFAULT_TEST_ON_CREATE; 342 private volatile boolean testOnBorrow = BaseObjectPoolConfig.DEFAULT_TEST_ON_BORROW; 343 private volatile boolean testOnReturn = BaseObjectPoolConfig.DEFAULT_TEST_ON_RETURN; 344 private volatile boolean testWhileIdle = BaseObjectPoolConfig.DEFAULT_TEST_WHILE_IDLE; 345 private volatile Duration durationBetweenEvictionRuns = BaseObjectPoolConfig.DEFAULT_TIME_BETWEEN_EVICTION_RUNS; 346 private volatile int numTestsPerEvictionRun = BaseObjectPoolConfig.DEFAULT_NUM_TESTS_PER_EVICTION_RUN; 347 348 private volatile Duration minEvictableIdleDuration = BaseObjectPoolConfig.DEFAULT_MIN_EVICTABLE_IDLE_DURATION; 349 private volatile Duration softMinEvictableIdleDuration = BaseObjectPoolConfig.DEFAULT_SOFT_MIN_EVICTABLE_IDLE_DURATION; 350 private volatile EvictionPolicy<T> evictionPolicy; 351 private volatile Duration evictorShutdownTimeoutDuration = BaseObjectPoolConfig.DEFAULT_EVICTOR_SHUTDOWN_TIMEOUT; 352 // Internal (primarily state) attributes 353 final Object closeLock = new Object(); 354 volatile boolean closed; 355 356 final Object evictionLock = new Object(); 357 private Evictor evictor; // @GuardedBy("evictionLock") 358 EvictionIterator evictionIterator; // @GuardedBy("evictionLock") 359 360 /** 361 * Class loader for evictor thread to use since, in a JavaEE or similar 362 * environment, the context class loader for the evictor thread may not have 363 * visibility of the correct factory. See POOL-161. Uses a weak reference to 364 * avoid potential memory leaks if the Pool is discarded rather than closed. 365 */ 366 private final WeakReference<ClassLoader> factoryClassLoader; 367 // Monitoring (primarily JMX) attributes 368 private final ObjectName objectName; 369 private final String creationStackTrace; 370 private final AtomicLong borrowedCount = new AtomicLong(); 371 private final AtomicLong returnedCount = new AtomicLong(); 372 final AtomicLong createdCount = new AtomicLong(); 373 final AtomicLong destroyedCount = new AtomicLong(); 374 final AtomicLong destroyedByEvictorCount = new AtomicLong(); 375 final AtomicLong destroyedByBorrowValidationCount = new AtomicLong(); 376 377 private final StatsStore activeTimes = new StatsStore(MEAN_TIMING_STATS_CACHE_SIZE); 378 private final StatsStore idleTimes = new StatsStore(MEAN_TIMING_STATS_CACHE_SIZE); 379 private final StatsStore waitTimes = new StatsStore(MEAN_TIMING_STATS_CACHE_SIZE); 380 381 private final AtomicReference<Duration> maxBorrowWaitDuration = new AtomicReference<>(Duration.ZERO); 382 383 private volatile SwallowedExceptionListener swallowedExceptionListener; 384 private volatile boolean messageStatistics; 385 386 /** Additional configuration properties for abandoned object tracking. */ 387 protected volatile AbandonedConfig abandonedConfig; 388 389 /** 390 * Handles JMX registration (if required) and the initialization required for 391 * monitoring. 392 * 393 * @param config Pool configuration 394 * @param jmxNameBase The default base JMX name for the new pool unless 395 * overridden by the config 396 * @param jmxNamePrefix Prefix to be used for JMX name for the new pool 397 */ 398 public BaseGenericObjectPool(final BaseObjectPoolConfig<T> config, 399 final String jmxNameBase, final String jmxNamePrefix) { 400 if (config.getJmxEnabled()) { 401 this.objectName = jmxRegister(config, jmxNameBase, jmxNamePrefix); 402 } else { 403 this.objectName = null; 404 } 405 406 // Populate the creation stack trace 407 this.creationStackTrace = getStackTrace(new Exception()); 408 409 // save the current TCCL (if any) to be used later by the evictor Thread 410 final ClassLoader cl = Thread.currentThread().getContextClassLoader(); 411 if (cl == null) { 412 factoryClassLoader = null; 413 } else { 414 factoryClassLoader = new WeakReference<>(cl); 415 } 416 417 fairness = config.getFairness(); 418 } 419 420 /** 421 * Appends statistics if enabled. 422 * <p> 423 * Statistics may not accurately reflect snapshot state at the time of the exception because we do not want to lock the pool when gathering this 424 * information. 425 * </p> 426 * 427 * @param string The root string. 428 * @return The root string plus statistics. 429 */ 430 String appendStats(final String string) { 431 return messageStatistics ? string + ", " + getStatsString() : string; 432 } 433 434 /** 435 * Verifies that the pool is open. 436 * @throws IllegalStateException if the pool is closed. 437 */ 438 final void assertOpen() throws IllegalStateException { 439 if (isClosed()) { 440 throw new IllegalStateException("Pool not open"); 441 } 442 } 443 444 /** 445 * Closes the pool, destroys the remaining idle objects and, if registered 446 * in JMX, deregisters it. 447 */ 448 public abstract void close(); 449 450 /** 451 * Creates a list of pooled objects to remove based on their state. 452 * @param abandonedConfig The abandoned configuration. 453 * @param allObjects PooledObject instances to consider. 454 * @return a list of pooled objects to remove based on their state. 455 */ 456 ArrayList<PooledObject<T>> createRemoveList(final AbandonedConfig abandonedConfig, final Map<IdentityWrapper<T>, PooledObject<T>> allObjects) { 457 final Instant timeout = Instant.now().minus(abandonedConfig.getRemoveAbandonedTimeoutDuration()); 458 final ArrayList<PooledObject<T>> remove = new ArrayList<>(); 459 allObjects.values().forEach(pooledObject -> { 460 synchronized (pooledObject) { 461 if (pooledObject.getState() == PooledObjectState.ALLOCATED && 462 pooledObject.getLastUsedInstant().compareTo(timeout) <= 0) { 463 pooledObject.markAbandoned(); 464 remove.add(pooledObject); 465 } 466 } 467 }); 468 return remove; 469 } 470 471 /** 472 * Tries to ensure that the configured minimum number of idle instances are 473 * available in the pool. 474 * @throws Exception if an error occurs creating idle instances 475 */ 476 abstract void ensureMinIdle() throws Exception; 477 478 /** 479 * Perform {@code numTests} idle object eviction tests, evicting 480 * examined objects that meet the criteria for eviction. If 481 * {@code testWhileIdle} is true, examined objects are validated 482 * when visited (and removed if invalid); otherwise only objects that 483 * have been idle for more than {@code minEvicableIdleTimeMillis} 484 * are removed. 485 * 486 * @throws Exception when there is a problem evicting idle objects. 487 */ 488 public abstract void evict() throws Exception; 489 490 /** 491 * Gets whether to block when the {@code borrowObject()} method is 492 * invoked when the pool is exhausted (the maximum number of "active" 493 * objects has been reached). 494 * 495 * @return {@code true} if {@code borrowObject()} should block 496 * when the pool is exhausted 497 * 498 * @see #setBlockWhenExhausted 499 */ 500 public final boolean getBlockWhenExhausted() { 501 return blockWhenExhausted; 502 } 503 504 /** 505 * The total number of objects successfully borrowed from this pool over the 506 * lifetime of the pool. 507 * @return the borrowed object count 508 */ 509 public final long getBorrowedCount() { 510 return borrowedCount.get(); 511 } 512 513 /** 514 * The total number of objects created for this pool over the lifetime of 515 * the pool. 516 * @return the created object count 517 */ 518 public final long getCreatedCount() { 519 return createdCount.get(); 520 } 521 522 /** 523 * Provides the stack trace for the call that created this pool. JMX 524 * registration may trigger a memory leak so it is important that pools are 525 * deregistered when no longer used by calling the {@link #close()} method. 526 * This method is provided to assist with identifying code that creates but 527 * does not close it thereby creating a memory leak. 528 * @return pool creation stack trace 529 */ 530 public final String getCreationStackTrace() { 531 return creationStackTrace; 532 } 533 534 /** 535 * The total number of objects destroyed by this pool as a result of failing 536 * validation during {@code borrowObject()} over the lifetime of the 537 * pool. 538 * @return validation destroyed object count 539 */ 540 public final long getDestroyedByBorrowValidationCount() { 541 return destroyedByBorrowValidationCount.get(); 542 } 543 544 /** 545 * The total number of objects destroyed by the evictor associated with this 546 * pool over the lifetime of the pool. 547 * @return the evictor destroyed object count 548 */ 549 public final long getDestroyedByEvictorCount() { 550 return destroyedByEvictorCount.get(); 551 } 552 553 /** 554 * The total number of objects destroyed by this pool over the lifetime of 555 * the pool. 556 * @return the destroyed object count 557 */ 558 public final long getDestroyedCount() { 559 return destroyedCount.get(); 560 } 561 562 /** 563 * Gets the {@link EvictionPolicy} defined for this pool. 564 * 565 * @return the eviction policy 566 * @since 2.4 567 * @since 2.6.0 Changed access from protected to public. 568 */ 569 public EvictionPolicy<T> getEvictionPolicy() { 570 return evictionPolicy; 571 } 572 573 /** 574 * Gets the name of the {@link EvictionPolicy} implementation that is 575 * used by this pool. 576 * 577 * @return The fully qualified class name of the {@link EvictionPolicy} 578 * 579 * @see #setEvictionPolicyClassName(String) 580 */ 581 public final String getEvictionPolicyClassName() { 582 return evictionPolicy.getClass().getName(); 583 } 584 585 /** 586 * Gets the timeout that will be used when waiting for the Evictor to 587 * shutdown if this pool is closed and it is the only pool still using the 588 * the value for the Evictor. 589 * 590 * @return The timeout that will be used while waiting for 591 * the Evictor to shut down. 592 * @since 2.10.0 593 * @deprecated Use {@link #getEvictorShutdownTimeoutDuration()}. 594 */ 595 @Deprecated 596 public final Duration getEvictorShutdownTimeout() { 597 return evictorShutdownTimeoutDuration; 598 } 599 600 /** 601 * Gets the timeout that will be used when waiting for the Evictor to 602 * shutdown if this pool is closed and it is the only pool still using the 603 * the value for the Evictor. 604 * 605 * @return The timeout that will be used while waiting for 606 * the Evictor to shut down. 607 * @since 2.11.0 608 */ 609 public final Duration getEvictorShutdownTimeoutDuration() { 610 return evictorShutdownTimeoutDuration; 611 } 612 613 /** 614 * Gets the timeout that will be used when waiting for the Evictor to 615 * shutdown if this pool is closed and it is the only pool still using the 616 * the value for the Evictor. 617 * 618 * @return The timeout in milliseconds that will be used while waiting for 619 * the Evictor to shut down. 620 * @deprecated Use {@link #getEvictorShutdownTimeoutDuration()}. 621 */ 622 @Deprecated 623 public final long getEvictorShutdownTimeoutMillis() { 624 return evictorShutdownTimeoutDuration.toMillis(); 625 } 626 627 /** 628 * Gets whether or not the pool serves threads waiting to borrow objects fairly. 629 * True means that waiting threads are served as if waiting in a FIFO queue. 630 * 631 * @return {@code true} if waiting threads are to be served 632 * by the pool in arrival order 633 */ 634 public final boolean getFairness() { 635 return fairness; 636 } 637 638 /** 639 * Provides the name under which the pool has been registered with the 640 * platform MBean server or {@code null} if the pool has not been 641 * registered. 642 * @return the JMX name 643 */ 644 public final ObjectName getJmxName() { 645 return objectName; 646 } 647 648 /** 649 * Gets whether the pool has LIFO (last in, first out) behavior with 650 * respect to idle objects - always returning the most recently used object 651 * from the pool, or as a FIFO (first in, first out) queue, where the pool 652 * always returns the oldest object in the idle object pool. 653 * 654 * @return {@code true} if the pool is configured with LIFO behavior 655 * or {@code false} if the pool is configured with FIFO 656 * behavior 657 * 658 * @see #setLifo 659 */ 660 public final boolean getLifo() { 661 return lifo; 662 } 663 664 /** 665 * Gets whether this pool identifies and logs any abandoned objects. 666 * 667 * @return {@code true} if abandoned object removal is configured for this 668 * pool and removal events are to be logged otherwise {@code false} 669 * 670 * @see AbandonedConfig#getLogAbandoned() 671 * @since 2.11.0 672 */ 673 public boolean getLogAbandoned() { 674 final AbandonedConfig ac = this.abandonedConfig; 675 return ac != null && ac.getLogAbandoned(); 676 } 677 678 /** 679 * Gets the maximum time a thread has waited to borrow objects from the pool. 680 * @return maximum wait time in milliseconds since the pool was created 681 */ 682 public final long getMaxBorrowWaitTimeMillis() { 683 return maxBorrowWaitDuration.get().toMillis(); 684 } 685 686 /** 687 * Gets the maximum number of objects that can be allocated by the pool 688 * (checked out to clients, or idle awaiting checkout) at a given time. When 689 * negative, there is no limit to the number of objects that can be 690 * managed by the pool at one time. 691 * 692 * @return the cap on the total number of object instances managed by the 693 * pool. 694 * 695 * @see #setMaxTotal 696 */ 697 public final int getMaxTotal() { 698 return maxTotal; 699 } 700 701 /** 702 * Gets the maximum duration the 703 * {@code borrowObject()} method should block before throwing an 704 * exception when the pool is exhausted and 705 * {@link #getBlockWhenExhausted} is true. When less than 0, the 706 * {@code borrowObject()} method may block indefinitely. 707 * 708 * @return the maximum number of milliseconds {@code borrowObject()} 709 * will block. 710 * 711 * @see #setMaxWait 712 * @see #setBlockWhenExhausted 713 * @since 2.11.0 714 */ 715 public final Duration getMaxWaitDuration() { 716 return maxWaitDuration; 717 } 718 719 /** 720 * Gets the maximum amount of time (in milliseconds) the 721 * {@code borrowObject()} method should block before throwing an 722 * exception when the pool is exhausted and 723 * {@link #getBlockWhenExhausted} is true. When less than 0, the 724 * {@code borrowObject()} method may block indefinitely. 725 * 726 * @return the maximum number of milliseconds {@code borrowObject()} 727 * will block. 728 * 729 * @see #setMaxWait 730 * @see #setBlockWhenExhausted 731 * @deprecated Use {@link #getMaxWaitDuration()}. 732 */ 733 @Deprecated 734 public final long getMaxWaitMillis() { 735 return maxWaitDuration.toMillis(); 736 } 737 738 /** 739 * The mean time objects are active for based on the last {@link 740 * #MEAN_TIMING_STATS_CACHE_SIZE} objects returned to the pool. 741 * @return mean time an object has been checked out from the pool among 742 * recently returned objects 743 */ 744 public final long getMeanActiveTimeMillis() { 745 return activeTimes.getMean(); 746 } 747 748 /** 749 * The mean time threads wait to borrow an object based on the last {@link 750 * #MEAN_TIMING_STATS_CACHE_SIZE} objects borrowed from the pool. 751 * @return mean time in milliseconds that a recently served thread has had 752 * to wait to borrow an object from the pool 753 */ 754 public final long getMeanBorrowWaitTimeMillis() { 755 return waitTimes.getMean(); 756 } 757 758 /** 759 * The mean time objects are idle for based on the last {@link 760 * #MEAN_TIMING_STATS_CACHE_SIZE} objects borrowed from the pool. 761 * @return mean time an object has been idle in the pool among recently 762 * borrowed objects 763 */ 764 public final long getMeanIdleTimeMillis() { 765 return idleTimes.getMean(); 766 } 767 768 /** 769 * Gets whether to include statistics in exception messages. 770 * <p> 771 * Statistics may not accurately reflect snapshot state at the time of the exception because we do not want to lock the pool when gathering this 772 * information. 773 * </p> 774 * 775 * @return whether to include statistics in exception messages. 776 * @since 2.11.0 777 */ 778 public boolean getMessageStatistics() { 779 return messageStatistics; 780 } 781 782 /** 783 * Gets the minimum amount of time an object may sit idle in the pool 784 * before it is eligible for eviction by the idle object evictor (if any - 785 * see {@link #setTimeBetweenEvictionRuns(Duration)}). When non-positive, 786 * no objects will be evicted from the pool due to idle time alone. 787 * 788 * @return minimum amount of time an object may sit idle in the pool before 789 * it is eligible for eviction 790 * 791 * @see #setMinEvictableIdleTimeMillis 792 * @see #setTimeBetweenEvictionRunsMillis 793 * @since 2.11.0 794 */ 795 public final Duration getMinEvictableIdleDuration() { 796 return minEvictableIdleDuration; 797 } 798 799 /** 800 * Gets the minimum amount of time an object may sit idle in the pool 801 * before it is eligible for eviction by the idle object evictor (if any - 802 * see {@link #setTimeBetweenEvictionRuns(Duration)}). When non-positive, 803 * no objects will be evicted from the pool due to idle time alone. 804 * 805 * @return minimum amount of time an object may sit idle in the pool before 806 * it is eligible for eviction 807 * 808 * @see #setMinEvictableIdleTimeMillis 809 * @see #setTimeBetweenEvictionRunsMillis 810 * @since 2.10.0 811 * @deprecated Use {@link #getMinEvictableIdleDuration()}. 812 */ 813 @Deprecated 814 public final Duration getMinEvictableIdleTime() { 815 return minEvictableIdleDuration; 816 } 817 818 /** 819 * Gets the minimum amount of time an object may sit idle in the pool 820 * before it is eligible for eviction by the idle object evictor (if any - 821 * see {@link #setTimeBetweenEvictionRunsMillis(long)}). When non-positive, 822 * no objects will be evicted from the pool due to idle time alone. 823 * 824 * @return minimum amount of time an object may sit idle in the pool before 825 * it is eligible for eviction 826 * 827 * @see #setMinEvictableIdleTimeMillis 828 * @see #setTimeBetweenEvictionRunsMillis 829 * @deprecated Use {@link #getMinEvictableIdleDuration()}. 830 */ 831 @Deprecated 832 public final long getMinEvictableIdleTimeMillis() { 833 return minEvictableIdleDuration.toMillis(); 834 } 835 836 /** 837 * The number of instances currently idle in this pool. 838 * @return count of instances available for checkout from the pool 839 */ 840 public abstract int getNumIdle(); 841 842 /** 843 * Gets the maximum number of objects to examine during each run (if any) 844 * of the idle object evictor thread. When positive, the number of tests 845 * performed for a run will be the minimum of the configured value and the 846 * number of idle instances in the pool. When negative, the number of tests 847 * performed will be <code>ceil({@link #getNumIdle}/ 848 * abs({@link #getNumTestsPerEvictionRun}))</code> which means that when the 849 * value is {@code -n} roughly one nth of the idle objects will be 850 * tested per run. 851 * 852 * @return max number of objects to examine during each evictor run 853 * 854 * @see #setNumTestsPerEvictionRun 855 * @see #setTimeBetweenEvictionRunsMillis 856 */ 857 public final int getNumTestsPerEvictionRun() { 858 return numTestsPerEvictionRun; 859 } 860 861 /** 862 * Gets whether a check is made for abandoned objects when an object is borrowed 863 * from this pool. 864 * 865 * @return {@code true} if abandoned object removal is configured to be 866 * activated by borrowObject otherwise {@code false} 867 * 868 * @see AbandonedConfig#getRemoveAbandonedOnBorrow() 869 * @since 2.11.0 870 */ 871 public boolean getRemoveAbandonedOnBorrow() { 872 final AbandonedConfig ac = this.abandonedConfig; 873 return ac != null && ac.getRemoveAbandonedOnBorrow(); 874 } 875 876 /** 877 * Gets whether a check is made for abandoned objects when the evictor runs. 878 * 879 * @return {@code true} if abandoned object removal is configured to be 880 * activated when the evictor runs otherwise {@code false} 881 * 882 * @see AbandonedConfig#getRemoveAbandonedOnMaintenance() 883 * @since 2.11.0 884 */ 885 public boolean getRemoveAbandonedOnMaintenance() { 886 final AbandonedConfig ac = this.abandonedConfig; 887 return ac != null && ac.getRemoveAbandonedOnMaintenance(); 888 } 889 890 /** 891 * Gets the timeout before which an object will be considered to be 892 * abandoned by this pool. 893 * 894 * @return The abandoned object timeout in seconds if abandoned object 895 * removal is configured for this pool; Integer.MAX_VALUE otherwise. 896 * 897 * @see AbandonedConfig#getRemoveAbandonedTimeoutDuration() 898 * @see AbandonedConfig#getRemoveAbandonedTimeoutDuration() 899 * @deprecated Use {@link #getRemoveAbandonedTimeoutDuration()}. 900 * @since 2.11.0 901 */ 902 @Deprecated 903 public int getRemoveAbandonedTimeout() { 904 return (int) getRemoveAbandonedTimeoutDuration().getSeconds(); 905 } 906 907 /** 908 * Gets the timeout before which an object will be considered to be 909 * abandoned by this pool. 910 * 911 * @return The abandoned object timeout in seconds if abandoned object 912 * removal is configured for this pool; Integer.MAX_VALUE otherwise. 913 * 914 * @see AbandonedConfig#getRemoveAbandonedTimeoutDuration() 915 * @since 2.11.0 916 */ 917 public Duration getRemoveAbandonedTimeoutDuration() { 918 final AbandonedConfig ac = this.abandonedConfig; 919 return ac != null ? ac.getRemoveAbandonedTimeoutDuration() : DEFAULT_REMOVE_ABANDONED_TIMEOUT; 920 } 921 922 /** 923 * The total number of objects returned to this pool over the lifetime of 924 * the pool. This excludes attempts to return the same object multiple 925 * times. 926 * @return the returned object count 927 */ 928 public final long getReturnedCount() { 929 return returnedCount.get(); 930 } 931 932 /** 933 * Gets the minimum amount of time an object may sit idle in the pool 934 * before it is eligible for eviction by the idle object evictor (if any - 935 * see {@link #setTimeBetweenEvictionRuns(Duration)}), 936 * with the extra condition that at least {@code minIdle} object 937 * instances remain in the pool. This setting is overridden by 938 * {@link #getMinEvictableIdleTime} (that is, if 939 * {@link #getMinEvictableIdleTime} is positive, then 940 * {@link #getSoftMinEvictableIdleTime} is ignored). 941 * 942 * @return minimum amount of time an object may sit idle in the pool before 943 * it is eligible for eviction if minIdle instances are available 944 * 945 * @see #setSoftMinEvictableIdle(Duration) 946 * @since 2.11.0 947 */ 948 public final Duration getSoftMinEvictableIdleDuration() { 949 return softMinEvictableIdleDuration; 950 } 951 952 /** 953 * Gets the minimum amount of time an object may sit idle in the pool 954 * before it is eligible for eviction by the idle object evictor (if any - 955 * see {@link #setTimeBetweenEvictionRuns(Duration)}), 956 * with the extra condition that at least {@code minIdle} object 957 * instances remain in the pool. This setting is overridden by 958 * {@link #getMinEvictableIdleTime} (that is, if 959 * {@link #getMinEvictableIdleTime} is positive, then 960 * {@link #getSoftMinEvictableIdleTime} is ignored). 961 * 962 * @return minimum amount of time an object may sit idle in the pool before 963 * it is eligible for eviction if minIdle instances are available 964 * 965 * @see #setSoftMinEvictableIdle(Duration) 966 * @since 2.10.0 967 * @deprecated Use {@link #getSoftMinEvictableIdleDuration}. 968 */ 969 @Deprecated 970 public final Duration getSoftMinEvictableIdleTime() { 971 return softMinEvictableIdleDuration; 972 } 973 974 /** 975 * Gets the minimum amount of time an object may sit idle in the pool 976 * before it is eligible for eviction by the idle object evictor (if any - 977 * see {@link #setTimeBetweenEvictionRunsMillis(long)}), 978 * with the extra condition that at least {@code minIdle} object 979 * instances remain in the pool. This setting is overridden by 980 * {@link #getMinEvictableIdleTimeMillis} (that is, if 981 * {@link #getMinEvictableIdleTimeMillis} is positive, then 982 * {@link #getSoftMinEvictableIdleTimeMillis} is ignored). 983 * 984 * @return minimum amount of time an object may sit idle in the pool before 985 * it is eligible for eviction if minIdle instances are available 986 * 987 * @see #setSoftMinEvictableIdleTimeMillis 988 * @deprecated Use {@link #getSoftMinEvictableIdleTime()}. 989 */ 990 @Deprecated 991 public final long getSoftMinEvictableIdleTimeMillis() { 992 return softMinEvictableIdleDuration.toMillis(); 993 } 994 995 /** 996 * Gets the stack trace of an exception as a string. 997 * @param e exception to trace 998 * @return exception stack trace as a string 999 */ 1000 private String getStackTrace(final Exception e) { 1001 // Need the exception in string form to prevent the retention of 1002 // references to classes in the stack trace that could trigger a memory 1003 // leak in a container environment. 1004 final Writer w = new StringWriter(); 1005 final PrintWriter pw = new PrintWriter(w); 1006 e.printStackTrace(pw); 1007 return w.toString(); 1008 } 1009 1010 /** 1011 * Gets a statistics string. 1012 * 1013 * @return a statistics string. 1014 */ 1015 String getStatsString() { 1016 // Simply listed in AB order. 1017 return String.format( 1018 "activeTimes=%s, blockWhenExhausted=%s, borrowedCount=%,d, closed=%s, createdCount=%,d, destroyedByBorrowValidationCount=%,d, " + 1019 "destroyedByEvictorCount=%,d, evictorShutdownTimeoutDuration=%s, fairness=%s, idleTimes=%s, lifo=%s, maxBorrowWaitDuration=%s, " + 1020 "maxTotal=%s, maxWaitDuration=%s, minEvictableIdleDuration=%s, numTestsPerEvictionRun=%s, returnedCount=%s, " + 1021 "softMinEvictableIdleDuration=%s, testOnBorrow=%s, testOnCreate=%s, testOnReturn=%s, testWhileIdle=%s, " + 1022 "durationBetweenEvictionRuns=%s, waitTimes=%s", 1023 activeTimes.getCurrentValues(), blockWhenExhausted, borrowedCount.get(), closed, createdCount.get(), destroyedByBorrowValidationCount.get(), 1024 destroyedByEvictorCount.get(), evictorShutdownTimeoutDuration, fairness, idleTimes.getCurrentValues(), lifo, maxBorrowWaitDuration.get(), 1025 maxTotal, maxWaitDuration, minEvictableIdleDuration, numTestsPerEvictionRun, returnedCount, softMinEvictableIdleDuration, testOnBorrow, 1026 testOnCreate, testOnReturn, testWhileIdle, durationBetweenEvictionRuns, waitTimes.getCurrentValues()); 1027 } 1028 1029 /** 1030 * Gets the listener used (if any) to receive notifications of exceptions 1031 * unavoidably swallowed by the pool. 1032 * 1033 * @return The listener or {@code null} for no listener 1034 */ 1035 public final SwallowedExceptionListener getSwallowedExceptionListener() { 1036 return swallowedExceptionListener; 1037 } 1038 1039 /** 1040 * Gets whether objects borrowed from the pool will be validated before 1041 * being returned from the {@code borrowObject()} method. Validation is 1042 * performed by the {@code validateObject()} method of the factory 1043 * associated with the pool. If the object fails to validate, it will be 1044 * removed from the pool and destroyed, and a new attempt will be made to 1045 * borrow an object from the pool. 1046 * 1047 * @return {@code true} if objects are validated before being returned 1048 * from the {@code borrowObject()} method 1049 * 1050 * @see #setTestOnBorrow 1051 */ 1052 public final boolean getTestOnBorrow() { 1053 return testOnBorrow; 1054 } 1055 1056 /** 1057 * Gets whether objects created for the pool will be validated before 1058 * being returned from the {@code borrowObject()} method. Validation is 1059 * performed by the {@code validateObject()} method of the factory 1060 * associated with the pool. If the object fails to validate, then 1061 * {@code borrowObject()} will fail. 1062 * 1063 * @return {@code true} if newly created objects are validated before 1064 * being returned from the {@code borrowObject()} method 1065 * 1066 * @see #setTestOnCreate 1067 * 1068 * @since 2.2 1069 */ 1070 public final boolean getTestOnCreate() { 1071 return testOnCreate; 1072 } 1073 1074 /** 1075 * Gets whether objects borrowed from the pool will be validated when 1076 * they are returned to the pool via the {@code returnObject()} method. 1077 * Validation is performed by the {@code validateObject()} method of 1078 * the factory associated with the pool. Returning objects that fail validation 1079 * are destroyed rather then being returned the pool. 1080 * 1081 * @return {@code true} if objects are validated on return to 1082 * the pool via the {@code returnObject()} method 1083 * 1084 * @see #setTestOnReturn 1085 */ 1086 public final boolean getTestOnReturn() { 1087 return testOnReturn; 1088 } 1089 1090 /** 1091 * Gets whether objects sitting idle in the pool will be validated by the 1092 * idle object evictor (if any - see 1093 * {@link #setTimeBetweenEvictionRuns(Duration)}). Validation is performed 1094 * by the {@code validateObject()} method of the factory associated 1095 * with the pool. If the object fails to validate, it will be removed from 1096 * the pool and destroyed. 1097 * 1098 * @return {@code true} if objects will be validated by the evictor 1099 * 1100 * @see #setTestWhileIdle 1101 * @see #setTimeBetweenEvictionRunsMillis 1102 */ 1103 public final boolean getTestWhileIdle() { 1104 return testWhileIdle; 1105 } 1106 1107 /** 1108 * Gets the duration to sleep between runs of the idle 1109 * object evictor thread. When non-positive, no idle object evictor thread 1110 * will be run. 1111 * 1112 * @return number of milliseconds to sleep between evictor runs 1113 * 1114 * @see #setTimeBetweenEvictionRuns 1115 * @since 2.11.0 1116 */ 1117 public final Duration getDurationBetweenEvictionRuns() { 1118 return durationBetweenEvictionRuns; 1119 } 1120 1121 /** 1122 * Gets the duration to sleep between runs of the idle 1123 * object evictor thread. When non-positive, no idle object evictor thread 1124 * will be run. 1125 * 1126 * @return number of milliseconds to sleep between evictor runs 1127 * 1128 * @see #setTimeBetweenEvictionRuns 1129 * @since 2.10.0 1130 * @deprecated {@link #getDurationBetweenEvictionRuns()}. 1131 */ 1132 @Deprecated 1133 public final Duration getTimeBetweenEvictionRuns() { 1134 return durationBetweenEvictionRuns; 1135 } 1136 1137 /** 1138 * Gets the number of milliseconds to sleep between runs of the idle 1139 * object evictor thread. When non-positive, no idle object evictor thread 1140 * will be run. 1141 * 1142 * @return number of milliseconds to sleep between evictor runs 1143 * 1144 * @see #setTimeBetweenEvictionRunsMillis 1145 * @deprecated Use {@link #getDurationBetweenEvictionRuns()}. 1146 */ 1147 @Deprecated 1148 public final long getTimeBetweenEvictionRunsMillis() { 1149 return durationBetweenEvictionRuns.toMillis(); 1150 } 1151 1152 // Monitoring (primarily JMX) related methods 1153 1154 /** 1155 * Gets whether or not abandoned object removal is configured for this pool. 1156 * 1157 * @return true if this pool is configured to detect and remove 1158 * abandoned objects 1159 * @since 2.11.0 1160 */ 1161 public boolean isAbandonedConfig() { 1162 return abandonedConfig != null; 1163 } 1164 1165 /** 1166 * Has this pool instance been closed. 1167 * @return {@code true} when this pool has been closed. 1168 */ 1169 public final boolean isClosed() { 1170 return closed; 1171 } 1172 1173 /** 1174 * Registers the pool with the platform MBean server. 1175 * The registered name will be 1176 * {@code jmxNameBase + jmxNamePrefix + i} where i is the least 1177 * integer greater than or equal to 1 such that the name is not already 1178 * registered. Swallows MBeanRegistrationException, NotCompliantMBeanException 1179 * returning null. 1180 * 1181 * @param config Pool configuration 1182 * @param jmxNameBase default base JMX name for this pool 1183 * @param jmxNamePrefix name prefix 1184 * @return registered ObjectName, null if registration fails 1185 */ 1186 private ObjectName jmxRegister(final BaseObjectPoolConfig<T> config, 1187 final String jmxNameBase, String jmxNamePrefix) { 1188 ObjectName newObjectName = null; 1189 final MBeanServer mbs = ManagementFactory.getPlatformMBeanServer(); 1190 int i = 1; 1191 boolean registered = false; 1192 String base = config.getJmxNameBase(); 1193 if (base == null) { 1194 base = jmxNameBase; 1195 } 1196 while (!registered) { 1197 try { 1198 ObjectName objName; 1199 // Skip the numeric suffix for the first pool in case there is 1200 // only one so the names are cleaner. 1201 if (i == 1) { 1202 objName = new ObjectName(base + jmxNamePrefix); 1203 } else { 1204 objName = new ObjectName(base + jmxNamePrefix + i); 1205 } 1206 mbs.registerMBean(this, objName); 1207 newObjectName = objName; 1208 registered = true; 1209 } catch (final MalformedObjectNameException e) { 1210 if (BaseObjectPoolConfig.DEFAULT_JMX_NAME_PREFIX.equals( 1211 jmxNamePrefix) && jmxNameBase.equals(base)) { 1212 // Shouldn't happen. Skip registration if it does. 1213 registered = true; 1214 } else { 1215 // Must be an invalid name. Use the defaults instead. 1216 jmxNamePrefix = 1217 BaseObjectPoolConfig.DEFAULT_JMX_NAME_PREFIX; 1218 base = jmxNameBase; 1219 } 1220 } catch (final InstanceAlreadyExistsException e) { 1221 // Increment the index and try again 1222 i++; 1223 } catch (final MBeanRegistrationException | NotCompliantMBeanException e) { 1224 // Shouldn't happen. Skip registration if it does. 1225 registered = true; 1226 } 1227 } 1228 return newObjectName; 1229 } 1230 1231 /** 1232 * Unregisters this pool's MBean. 1233 */ 1234 final void jmxUnregister() { 1235 if (objectName != null) { 1236 try { 1237 ManagementFactory.getPlatformMBeanServer().unregisterMBean(objectName); 1238 } catch (final MBeanRegistrationException | InstanceNotFoundException e) { 1239 swallowException(e); 1240 } 1241 } 1242 } 1243 1244 /** 1245 * Marks the object as returning to the pool. 1246 * @param pooledObject instance to return to the keyed pool 1247 */ 1248 protected void markReturningState(final PooledObject<T> pooledObject) { 1249 synchronized (pooledObject) { 1250 if (pooledObject.getState() != PooledObjectState.ALLOCATED) { 1251 throw new IllegalStateException("Object has already been returned to this pool or is invalid"); 1252 } 1253 pooledObject.markReturning(); // Keep from being marked abandoned 1254 } 1255 } 1256 1257 /** 1258 * Sets the abandoned object removal configuration. 1259 * 1260 * @param abandonedConfig the new configuration to use. This is used by value. 1261 * 1262 * @see AbandonedConfig 1263 * @since 2.11.0 1264 */ 1265 public void setAbandonedConfig(final AbandonedConfig abandonedConfig) { 1266 this.abandonedConfig = AbandonedConfig.copy(abandonedConfig); 1267 } 1268 1269 /** 1270 * Sets whether to block when the {@code borrowObject()} method is 1271 * invoked when the pool is exhausted (the maximum number of "active" 1272 * objects has been reached). 1273 * 1274 * @param blockWhenExhausted {@code true} if 1275 * {@code borrowObject()} should block 1276 * when the pool is exhausted 1277 * 1278 * @see #getBlockWhenExhausted 1279 */ 1280 public final void setBlockWhenExhausted(final boolean blockWhenExhausted) { 1281 this.blockWhenExhausted = blockWhenExhausted; 1282 } 1283 1284 /** 1285 * Initializes the receiver with the given configuration. 1286 * 1287 * @param config Initialization source. 1288 */ 1289 protected void setConfig(final BaseObjectPoolConfig<T> config) { 1290 setLifo(config.getLifo()); 1291 setMaxWait(config.getMaxWaitDuration()); 1292 setBlockWhenExhausted(config.getBlockWhenExhausted()); 1293 setTestOnCreate(config.getTestOnCreate()); 1294 setTestOnBorrow(config.getTestOnBorrow()); 1295 setTestOnReturn(config.getTestOnReturn()); 1296 setTestWhileIdle(config.getTestWhileIdle()); 1297 setNumTestsPerEvictionRun(config.getNumTestsPerEvictionRun()); 1298 setMinEvictableIdle(config.getMinEvictableIdleDuration()); 1299 setTimeBetweenEvictionRuns(config.getDurationBetweenEvictionRuns()); 1300 setSoftMinEvictableIdle(config.getSoftMinEvictableIdleDuration()); 1301 final EvictionPolicy<T> policy = config.getEvictionPolicy(); 1302 if (policy == null) { 1303 // Use the class name (pre-2.6.0 compatible) 1304 setEvictionPolicyClassName(config.getEvictionPolicyClassName()); 1305 } else { 1306 // Otherwise, use the class (2.6.0 feature) 1307 setEvictionPolicy(policy); 1308 } 1309 setEvictorShutdownTimeout(config.getEvictorShutdownTimeoutDuration()); 1310 } 1311 1312 /** 1313 * Sets the eviction policy for this pool. 1314 * 1315 * @param evictionPolicy 1316 * the eviction policy for this pool. 1317 * @since 2.6.0 1318 */ 1319 public void setEvictionPolicy(final EvictionPolicy<T> evictionPolicy) { 1320 this.evictionPolicy = evictionPolicy; 1321 } 1322 1323 /** 1324 * Sets the eviction policy. 1325 * 1326 * @param className Eviction policy class name. 1327 * @param classLoader Load the class from this class loader. 1328 */ 1329 @SuppressWarnings("unchecked") 1330 private void setEvictionPolicy(final String className, final ClassLoader classLoader) 1331 throws ClassNotFoundException, InstantiationException, IllegalAccessException, InvocationTargetException, NoSuchMethodException { 1332 final Class<?> clazz = Class.forName(className, true, classLoader); 1333 final Object policy = clazz.getConstructor().newInstance(); 1334 this.evictionPolicy = (EvictionPolicy<T>) policy; 1335 } 1336 1337 /** 1338 * Sets the name of the {@link EvictionPolicy} implementation that is used by this pool. The Pool will attempt to 1339 * load the class using the thread context class loader. If that fails, the use the class loader for the 1340 * {@link EvictionPolicy} interface. 1341 * 1342 * @param evictionPolicyClassName 1343 * the fully qualified class name of the new eviction policy 1344 * 1345 * @see #getEvictionPolicyClassName() 1346 * @since 2.6.0 If loading the class using the thread context class loader fails, use the class loader for the 1347 * {@link EvictionPolicy} interface. 1348 */ 1349 public final void setEvictionPolicyClassName(final String evictionPolicyClassName) { 1350 setEvictionPolicyClassName(evictionPolicyClassName, Thread.currentThread().getContextClassLoader()); 1351 } 1352 1353 /** 1354 * Sets the name of the {@link EvictionPolicy} implementation that is used by this pool. The Pool will attempt to 1355 * load the class using the given class loader. If that fails, use the class loader for the {@link EvictionPolicy} 1356 * interface. 1357 * 1358 * @param evictionPolicyClassName 1359 * the fully qualified class name of the new eviction policy 1360 * @param classLoader 1361 * the class loader to load the given {@code evictionPolicyClassName}. 1362 * 1363 * @see #getEvictionPolicyClassName() 1364 * @since 2.6.0 If loading the class using the given class loader fails, use the class loader for the 1365 * {@link EvictionPolicy} interface. 1366 */ 1367 public final void setEvictionPolicyClassName(final String evictionPolicyClassName, final ClassLoader classLoader) { 1368 // Getting epClass here and now best matches the caller's environment 1369 final Class<?> epClass = EvictionPolicy.class; 1370 final ClassLoader epClassLoader = epClass.getClassLoader(); 1371 try { 1372 try { 1373 setEvictionPolicy(evictionPolicyClassName, classLoader); 1374 } catch (final ClassCastException | ClassNotFoundException e) { 1375 setEvictionPolicy(evictionPolicyClassName, epClassLoader); 1376 } 1377 } catch (final ClassCastException e) { 1378 throw new IllegalArgumentException("Class " + evictionPolicyClassName + " from class loaders [" + 1379 classLoader + ", " + epClassLoader + "] do not implement " + EVICTION_POLICY_TYPE_NAME); 1380 } catch (final ClassNotFoundException | InstantiationException | IllegalAccessException | 1381 InvocationTargetException | NoSuchMethodException e) { 1382 throw new IllegalArgumentException( 1383 "Unable to create " + EVICTION_POLICY_TYPE_NAME + " instance of type " + evictionPolicyClassName, 1384 e); 1385 } 1386 } 1387 1388 /** 1389 * Sets the timeout that will be used when waiting for the Evictor to shutdown if this pool is closed and it is the 1390 * only pool still using the the value for the Evictor. 1391 * 1392 * @param evictorShutdownTimeout the timeout in milliseconds that will be used while waiting for the Evictor 1393 * to shut down. 1394 * @since 2.10.0 1395 */ 1396 public final void setEvictorShutdownTimeout(final Duration evictorShutdownTimeout) { 1397 this.evictorShutdownTimeoutDuration = PoolImplUtils.nonNull(evictorShutdownTimeout, BaseObjectPoolConfig.DEFAULT_EVICTOR_SHUTDOWN_TIMEOUT); 1398 } 1399 1400 /** 1401 * Sets the timeout that will be used when waiting for the Evictor to shutdown if this pool is closed and it is the 1402 * only pool still using the the value for the Evictor. 1403 * 1404 * @param evictorShutdownTimeoutMillis the timeout in milliseconds that will be used while waiting for the Evictor 1405 * to shut down. 1406 * @deprecated Use {@link #setEvictorShutdownTimeout(Duration)}. 1407 */ 1408 @Deprecated 1409 public final void setEvictorShutdownTimeoutMillis(final long evictorShutdownTimeoutMillis) { 1410 setEvictorShutdownTimeout(Duration.ofMillis(evictorShutdownTimeoutMillis)); 1411 } 1412 1413 /** 1414 * Sets whether the pool has LIFO (last in, first out) behavior with 1415 * respect to idle objects - always returning the most recently used object 1416 * from the pool, or as a FIFO (first in, first out) queue, where the pool 1417 * always returns the oldest object in the idle object pool. 1418 * 1419 * @param lifo {@code true} if the pool is to be configured with LIFO 1420 * behavior or {@code false} if the pool is to be 1421 * configured with FIFO behavior 1422 * 1423 * @see #getLifo() 1424 */ 1425 public final void setLifo(final boolean lifo) { 1426 this.lifo = lifo; 1427 } 1428 1429 /** 1430 * Sets the cap on the number of objects that can be allocated by the pool 1431 * (checked out to clients, or idle awaiting checkout) at a given time. Use 1432 * a negative value for no limit. 1433 * 1434 * @param maxTotal The cap on the total number of object instances managed 1435 * by the pool. Negative values mean that there is no limit 1436 * to the number of objects allocated by the pool. 1437 * 1438 * @see #getMaxTotal 1439 */ 1440 public final void setMaxTotal(final int maxTotal) { 1441 this.maxTotal = maxTotal; 1442 } 1443 1444 /** 1445 * Sets the maximum duration the 1446 * {@code borrowObject()} method should block before throwing an 1447 * exception when the pool is exhausted and 1448 * {@link #getBlockWhenExhausted} is true. When less than 0, the 1449 * {@code borrowObject()} method may block indefinitely. 1450 * 1451 * @param maxWaitDuration the maximum duration 1452 * {@code borrowObject()} will block or negative 1453 * for indefinitely. 1454 * 1455 * @see #getMaxWaitDuration 1456 * @see #setBlockWhenExhausted 1457 * @since 2.11.0 1458 */ 1459 public final void setMaxWait(final Duration maxWaitDuration) { 1460 this.maxWaitDuration = PoolImplUtils.nonNull(maxWaitDuration, BaseObjectPoolConfig.DEFAULT_MAX_WAIT); 1461 } 1462 1463 /** 1464 * Sets the maximum amount of time (in milliseconds) the 1465 * {@code borrowObject()} method should block before throwing an 1466 * exception when the pool is exhausted and 1467 * {@link #getBlockWhenExhausted} is true. When less than 0, the 1468 * {@code borrowObject()} method may block indefinitely. 1469 * 1470 * @param maxWaitMillis the maximum number of milliseconds 1471 * {@code borrowObject()} will block or negative 1472 * for indefinitely. 1473 * 1474 * @see #getMaxWaitDuration 1475 * @see #setBlockWhenExhausted 1476 * @deprecated Use {@link #setMaxWait}. 1477 */ 1478 @Deprecated 1479 public final void setMaxWaitMillis(final long maxWaitMillis) { 1480 setMaxWait(Duration.ofMillis(maxWaitMillis)); 1481 } 1482 1483 /** 1484 * Sets whether to include statistics in exception messages. 1485 * <p> 1486 * Statistics may not accurately reflect snapshot state at the time of the exception because we do not want to lock the pool when gathering this 1487 * information. 1488 * </p> 1489 * 1490 * @param messagesDetails whether to include statistics in exception messages. 1491 * @since 2.11.0 1492 */ 1493 public void setMessagesStatistics(final boolean messagesDetails) { 1494 this.messageStatistics = messagesDetails; 1495 } 1496 1497 /** 1498 * Sets the minimum amount of time an object may sit idle in the pool 1499 * before it is eligible for eviction by the idle object evictor (if any - 1500 * see {@link #setTimeBetweenEvictionRuns(Duration)}). When non-positive, 1501 * no objects will be evicted from the pool due to idle time alone. 1502 * 1503 * @param minEvictableIdleTime 1504 * minimum amount of time an object may sit idle in the pool 1505 * before it is eligible for eviction 1506 * 1507 * @see #getMinEvictableIdleTime 1508 * @see #setTimeBetweenEvictionRuns 1509 * @since 2.11.0 1510 */ 1511 public final void setMinEvictableIdle(final Duration minEvictableIdleTime) { 1512 this.minEvictableIdleDuration = PoolImplUtils.nonNull(minEvictableIdleTime, BaseObjectPoolConfig.DEFAULT_MIN_EVICTABLE_IDLE_DURATION); 1513 } 1514 1515 /** 1516 * Sets the minimum amount of time an object may sit idle in the pool 1517 * before it is eligible for eviction by the idle object evictor (if any - 1518 * see {@link #setTimeBetweenEvictionRuns(Duration)}). When non-positive, 1519 * no objects will be evicted from the pool due to idle time alone. 1520 * 1521 * @param minEvictableIdleTime 1522 * minimum amount of time an object may sit idle in the pool 1523 * before it is eligible for eviction 1524 * 1525 * @see #getMinEvictableIdleTime 1526 * @see #setTimeBetweenEvictionRuns 1527 * @since 2.10.0 1528 * @deprecated Use {@link #setMinEvictableIdle(Duration)}. 1529 */ 1530 @Deprecated 1531 public final void setMinEvictableIdleTime(final Duration minEvictableIdleTime) { 1532 this.minEvictableIdleDuration = PoolImplUtils.nonNull(minEvictableIdleTime, BaseObjectPoolConfig.DEFAULT_MIN_EVICTABLE_IDLE_DURATION); 1533 } 1534 1535 /** 1536 * Sets the minimum amount of time an object may sit idle in the pool 1537 * before it is eligible for eviction by the idle object evictor (if any - 1538 * see {@link #setTimeBetweenEvictionRunsMillis(long)}). When non-positive, 1539 * no objects will be evicted from the pool due to idle time alone. 1540 * 1541 * @param minEvictableIdleTimeMillis 1542 * minimum amount of time an object may sit idle in the pool 1543 * before it is eligible for eviction 1544 * 1545 * @see #getMinEvictableIdleTimeMillis 1546 * @see #setTimeBetweenEvictionRunsMillis 1547 * @deprecated Use {@link #setMinEvictableIdleTime(Duration)}. 1548 */ 1549 @Deprecated 1550 public final void setMinEvictableIdleTimeMillis(final long minEvictableIdleTimeMillis) { 1551 setMinEvictableIdleTime(Duration.ofMillis(minEvictableIdleTimeMillis)); 1552 } 1553 1554 /** 1555 * Sets the maximum number of objects to examine during each run (if any) 1556 * of the idle object evictor thread. When positive, the number of tests 1557 * performed for a run will be the minimum of the configured value and the 1558 * number of idle instances in the pool. When negative, the number of tests 1559 * performed will be <code>ceil({@link #getNumIdle}/ 1560 * abs({@link #getNumTestsPerEvictionRun}))</code> which means that when the 1561 * value is {@code -n} roughly one nth of the idle objects will be 1562 * tested per run. 1563 * 1564 * @param numTestsPerEvictionRun 1565 * max number of objects to examine during each evictor run 1566 * 1567 * @see #getNumTestsPerEvictionRun 1568 * @see #setTimeBetweenEvictionRunsMillis 1569 */ 1570 public final void setNumTestsPerEvictionRun(final int numTestsPerEvictionRun) { 1571 this.numTestsPerEvictionRun = numTestsPerEvictionRun; 1572 } 1573 1574 /** 1575 * Sets the minimum amount of time an object may sit idle in the pool 1576 * before it is eligible for eviction by the idle object evictor (if any - 1577 * see {@link #setTimeBetweenEvictionRuns(Duration)}), 1578 * with the extra condition that at least {@code minIdle} object 1579 * instances remain in the pool. This setting is overridden by 1580 * {@link #getMinEvictableIdleTime} (that is, if 1581 * {@link #getMinEvictableIdleTime} is positive, then 1582 * {@link #getSoftMinEvictableIdleTime} is ignored). 1583 * 1584 * @param softMinEvictableIdleTime 1585 * minimum amount of time an object may sit idle in the pool 1586 * before it is eligible for eviction if minIdle instances are 1587 * available 1588 * 1589 * @see #getSoftMinEvictableIdleTimeMillis 1590 * @since 2.11.0 1591 */ 1592 public final void setSoftMinEvictableIdle(final Duration softMinEvictableIdleTime) { 1593 this.softMinEvictableIdleDuration = PoolImplUtils.nonNull(softMinEvictableIdleTime, BaseObjectPoolConfig.DEFAULT_SOFT_MIN_EVICTABLE_IDLE_DURATION); 1594 } 1595 1596 /** 1597 * Sets the minimum amount of time an object may sit idle in the pool 1598 * before it is eligible for eviction by the idle object evictor (if any - 1599 * see {@link #setTimeBetweenEvictionRuns(Duration)}), 1600 * with the extra condition that at least {@code minIdle} object 1601 * instances remain in the pool. This setting is overridden by 1602 * {@link #getMinEvictableIdleTime} (that is, if 1603 * {@link #getMinEvictableIdleTime} is positive, then 1604 * {@link #getSoftMinEvictableIdleTime} is ignored). 1605 * 1606 * @param softMinEvictableIdleTime 1607 * minimum amount of time an object may sit idle in the pool 1608 * before it is eligible for eviction if minIdle instances are 1609 * available 1610 * 1611 * @see #getSoftMinEvictableIdleTimeMillis 1612 * @since 2.10.0 1613 * @deprecated Use {@link #setSoftMinEvictableIdle(Duration)}. 1614 */ 1615 @Deprecated 1616 public final void setSoftMinEvictableIdleTime(final Duration softMinEvictableIdleTime) { 1617 this.softMinEvictableIdleDuration = PoolImplUtils.nonNull(softMinEvictableIdleTime, BaseObjectPoolConfig.DEFAULT_SOFT_MIN_EVICTABLE_IDLE_DURATION); 1618 } 1619 1620 /** 1621 * Sets the minimum amount of time an object may sit idle in the pool 1622 * before it is eligible for eviction by the idle object evictor (if any - 1623 * see {@link #setTimeBetweenEvictionRunsMillis(long)}), 1624 * with the extra condition that at least {@code minIdle} object 1625 * instances remain in the pool. This setting is overridden by 1626 * {@link #getMinEvictableIdleTimeMillis} (that is, if 1627 * {@link #getMinEvictableIdleTimeMillis} is positive, then 1628 * {@link #getSoftMinEvictableIdleTimeMillis} is ignored). 1629 * 1630 * @param softMinEvictableIdleTimeMillis 1631 * minimum amount of time an object may sit idle in the pool 1632 * before it is eligible for eviction if minIdle instances are 1633 * available 1634 * 1635 * @see #getSoftMinEvictableIdleTimeMillis 1636 * @deprecated Use {@link #setSoftMinEvictableIdle(Duration)}. 1637 */ 1638 @Deprecated 1639 public final void setSoftMinEvictableIdleTimeMillis(final long softMinEvictableIdleTimeMillis) { 1640 setSoftMinEvictableIdleTime(Duration.ofMillis(softMinEvictableIdleTimeMillis)); 1641 } 1642 1643 /** 1644 * The listener used (if any) to receive notifications of exceptions 1645 * unavoidably swallowed by the pool. 1646 * 1647 * @param swallowedExceptionListener The listener or {@code null} 1648 * for no listener 1649 */ 1650 public final void setSwallowedExceptionListener( 1651 final SwallowedExceptionListener swallowedExceptionListener) { 1652 this.swallowedExceptionListener = swallowedExceptionListener; 1653 } 1654 1655 /** 1656 * Sets whether objects borrowed from the pool will be validated before 1657 * being returned from the {@code borrowObject()} method. Validation is 1658 * performed by the {@code validateObject()} method of the factory 1659 * associated with the pool. If the object fails to validate, it will be 1660 * removed from the pool and destroyed, and a new attempt will be made to 1661 * borrow an object from the pool. 1662 * 1663 * @param testOnBorrow {@code true} if objects should be validated 1664 * before being returned from the 1665 * {@code borrowObject()} method 1666 * 1667 * @see #getTestOnBorrow 1668 */ 1669 public final void setTestOnBorrow(final boolean testOnBorrow) { 1670 this.testOnBorrow = testOnBorrow; 1671 } 1672 1673 /** 1674 * Sets whether objects created for the pool will be validated before 1675 * being returned from the {@code borrowObject()} method. Validation is 1676 * performed by the {@code validateObject()} method of the factory 1677 * associated with the pool. If the object fails to validate, then 1678 * {@code borrowObject()} will fail. 1679 * 1680 * @param testOnCreate {@code true} if newly created objects should be 1681 * validated before being returned from the 1682 * {@code borrowObject()} method 1683 * 1684 * @see #getTestOnCreate 1685 * 1686 * @since 2.2 1687 */ 1688 public final void setTestOnCreate(final boolean testOnCreate) { 1689 this.testOnCreate = testOnCreate; 1690 } 1691 1692 /** 1693 * Sets whether objects borrowed from the pool will be validated when 1694 * they are returned to the pool via the {@code returnObject()} method. 1695 * Validation is performed by the {@code validateObject()} method of 1696 * the factory associated with the pool. Returning objects that fail validation 1697 * are destroyed rather then being returned the pool. 1698 * 1699 * @param testOnReturn {@code true} if objects are validated on 1700 * return to the pool via the 1701 * {@code returnObject()} method 1702 * 1703 * @see #getTestOnReturn 1704 */ 1705 public final void setTestOnReturn(final boolean testOnReturn) { 1706 this.testOnReturn = testOnReturn; 1707 } 1708 1709 /** 1710 * Sets whether objects sitting idle in the pool will be validated by the 1711 * idle object evictor (if any - see 1712 * {@link #setTimeBetweenEvictionRuns(Duration)}). Validation is performed 1713 * by the {@code validateObject()} method of the factory associated 1714 * with the pool. If the object fails to validate, it will be removed from 1715 * the pool and destroyed. Note that setting this property has no effect 1716 * unless the idle object evictor is enabled by setting 1717 * {@code timeBetweenEvictionRunsMillis} to a positive value. 1718 * 1719 * @param testWhileIdle 1720 * {@code true} so objects will be validated by the evictor 1721 * 1722 * @see #getTestWhileIdle 1723 * @see #setTimeBetweenEvictionRuns 1724 */ 1725 public final void setTestWhileIdle(final boolean testWhileIdle) { 1726 this.testWhileIdle = testWhileIdle; 1727 } 1728 1729 /** 1730 * Sets the number of milliseconds to sleep between runs of the idle object evictor thread. 1731 * <ul> 1732 * <li>When positive, the idle object evictor thread starts.</li> 1733 * <li>When non-positive, no idle object evictor thread runs.</li> 1734 * </ul> 1735 * 1736 * @param timeBetweenEvictionRuns 1737 * duration to sleep between evictor runs 1738 * 1739 * @see #getTimeBetweenEvictionRunsMillis 1740 * @since 2.10.0 1741 */ 1742 public final void setTimeBetweenEvictionRuns(final Duration timeBetweenEvictionRuns) { 1743 this.durationBetweenEvictionRuns = PoolImplUtils.nonNull(timeBetweenEvictionRuns, BaseObjectPoolConfig.DEFAULT_TIME_BETWEEN_EVICTION_RUNS); 1744 startEvictor(this.durationBetweenEvictionRuns); 1745 } 1746 1747 /** 1748 * Sets the number of milliseconds to sleep between runs of the idle object evictor thread. 1749 * <ul> 1750 * <li>When positive, the idle object evictor thread starts.</li> 1751 * <li>When non-positive, no idle object evictor thread runs.</li> 1752 * </ul> 1753 * 1754 * @param timeBetweenEvictionRunsMillis 1755 * number of milliseconds to sleep between evictor runs 1756 * 1757 * @see #getTimeBetweenEvictionRunsMillis 1758 * @deprecated Use {@link #setTimeBetweenEvictionRuns(Duration)}. 1759 */ 1760 @Deprecated 1761 public final void setTimeBetweenEvictionRunsMillis(final long timeBetweenEvictionRunsMillis) { 1762 setTimeBetweenEvictionRuns(Duration.ofMillis(timeBetweenEvictionRunsMillis)); 1763 } 1764 1765 /** 1766 * <p>Starts the evictor with the given delay. If there is an evictor 1767 * running when this method is called, it is stopped and replaced with a 1768 * new evictor with the specified delay.</p> 1769 * 1770 * <p>This method needs to be final, since it is called from a constructor. 1771 * See POOL-195.</p> 1772 * 1773 * @param delay time in milliseconds before start and between eviction runs 1774 */ 1775 final void startEvictor(final Duration delay) { 1776 synchronized (evictionLock) { 1777 final boolean isPositiverDelay = PoolImplUtils.isPositive(delay); 1778 if (evictor == null) { // Starting evictor for the first time or after a cancel 1779 if (isPositiverDelay) { // Starting new evictor 1780 evictor = new Evictor(); 1781 EvictionTimer.schedule(evictor, delay, delay); 1782 } 1783 } else if (isPositiverDelay) { // Stop or restart of existing evictor: Restart 1784 synchronized (EvictionTimer.class) { // Ensure no cancel can happen between cancel / schedule calls 1785 EvictionTimer.cancel(evictor, evictorShutdownTimeoutDuration, true); 1786 evictor = null; 1787 evictionIterator = null; 1788 evictor = new Evictor(); 1789 EvictionTimer.schedule(evictor, delay, delay); 1790 } 1791 } else { // Stopping evictor 1792 EvictionTimer.cancel(evictor, evictorShutdownTimeoutDuration, false); 1793 } 1794 } 1795 } 1796 1797 /** 1798 * Stops the evictor. 1799 */ 1800 void stopEvictor() { 1801 startEvictor(Duration.ofMillis(-1L)); 1802 } 1803 1804 /** 1805 * Swallows an exception and notifies the configured listener for swallowed 1806 * exceptions queue. 1807 * 1808 * @param swallowException exception to be swallowed 1809 */ 1810 final void swallowException(final Exception swallowException) { 1811 final SwallowedExceptionListener listener = getSwallowedExceptionListener(); 1812 1813 if (listener == null) { 1814 return; 1815 } 1816 1817 try { 1818 listener.onSwallowException(swallowException); 1819 } catch (final VirtualMachineError e) { 1820 throw e; 1821 } catch (final Throwable t) { 1822 // Ignore. Enjoy the irony. 1823 } 1824 } 1825 1826 @Override 1827 protected void toStringAppendFields(final StringBuilder builder) { 1828 builder.append("maxTotal="); 1829 builder.append(maxTotal); 1830 builder.append(", blockWhenExhausted="); 1831 builder.append(blockWhenExhausted); 1832 builder.append(", maxWaitDuration="); 1833 builder.append(maxWaitDuration); 1834 builder.append(", lifo="); 1835 builder.append(lifo); 1836 builder.append(", fairness="); 1837 builder.append(fairness); 1838 builder.append(", testOnCreate="); 1839 builder.append(testOnCreate); 1840 builder.append(", testOnBorrow="); 1841 builder.append(testOnBorrow); 1842 builder.append(", testOnReturn="); 1843 builder.append(testOnReturn); 1844 builder.append(", testWhileIdle="); 1845 builder.append(testWhileIdle); 1846 builder.append(", durationBetweenEvictionRuns="); 1847 builder.append(durationBetweenEvictionRuns); 1848 builder.append(", numTestsPerEvictionRun="); 1849 builder.append(numTestsPerEvictionRun); 1850 builder.append(", minEvictableIdleTimeDuration="); 1851 builder.append(minEvictableIdleDuration); 1852 builder.append(", softMinEvictableIdleTimeDuration="); 1853 builder.append(softMinEvictableIdleDuration); 1854 builder.append(", evictionPolicy="); 1855 builder.append(evictionPolicy); 1856 builder.append(", closeLock="); 1857 builder.append(closeLock); 1858 builder.append(", closed="); 1859 builder.append(closed); 1860 builder.append(", evictionLock="); 1861 builder.append(evictionLock); 1862 builder.append(", evictor="); 1863 builder.append(evictor); 1864 builder.append(", evictionIterator="); 1865 builder.append(evictionIterator); 1866 builder.append(", factoryClassLoader="); 1867 builder.append(factoryClassLoader); 1868 builder.append(", oname="); 1869 builder.append(objectName); 1870 builder.append(", creationStackTrace="); 1871 builder.append(creationStackTrace); 1872 builder.append(", borrowedCount="); 1873 builder.append(borrowedCount); 1874 builder.append(", returnedCount="); 1875 builder.append(returnedCount); 1876 builder.append(", createdCount="); 1877 builder.append(createdCount); 1878 builder.append(", destroyedCount="); 1879 builder.append(destroyedCount); 1880 builder.append(", destroyedByEvictorCount="); 1881 builder.append(destroyedByEvictorCount); 1882 builder.append(", destroyedByBorrowValidationCount="); 1883 builder.append(destroyedByBorrowValidationCount); 1884 builder.append(", activeTimes="); 1885 builder.append(activeTimes); 1886 builder.append(", idleTimes="); 1887 builder.append(idleTimes); 1888 builder.append(", waitTimes="); 1889 builder.append(waitTimes); 1890 builder.append(", maxBorrowWaitDuration="); 1891 builder.append(maxBorrowWaitDuration); 1892 builder.append(", swallowedExceptionListener="); 1893 builder.append(swallowedExceptionListener); 1894 } 1895 1896 /** 1897 * Updates statistics after an object is borrowed from the pool. 1898 * 1899 * @param p object borrowed from the pool 1900 * @param waitDuration that the borrowing thread had to wait 1901 */ 1902 final void updateStatsBorrow(final PooledObject<T> p, final Duration waitDuration) { 1903 borrowedCount.incrementAndGet(); 1904 idleTimes.add(p.getIdleDuration()); 1905 waitTimes.add(waitDuration); 1906 1907 // lock-free optimistic-locking maximum 1908 Duration currentMaxDuration; 1909 do { 1910 currentMaxDuration = maxBorrowWaitDuration.get(); 1911// if (currentMaxDuration >= waitDuration) { 1912// break; 1913// } 1914 if (currentMaxDuration.compareTo(waitDuration) >= 0) { 1915 break; 1916 } 1917 } while (!maxBorrowWaitDuration.compareAndSet(currentMaxDuration, waitDuration)); 1918 } 1919 1920 /** 1921 * Updates statistics after an object is returned to the pool. 1922 * 1923 * @param activeTime the amount of time (in milliseconds) that the returning 1924 * object was checked out 1925 */ 1926 final void updateStatsReturn(final Duration activeTime) { 1927 returnedCount.incrementAndGet(); 1928 activeTimes.add(activeTime); 1929 } 1930 1931 1932}