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