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