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