1 /*
2 * Licensed to the Apache Software Foundation (ASF) under one or more
3 * contributor license agreements. See the NOTICE file distributed with
4 * this work for additional information regarding copyright ownership.
5 * The ASF licenses this file to You under the Apache License, Version 2.0
6 * (the "License"); you may not use this file except in compliance with
7 * the License. You may obtain a copy of the License at
8 *
9 * https://www.apache.org/licenses/LICENSE-2.0
10 *
11 * Unless required by applicable law or agreed to in writing, software
12 * distributed under the License is distributed on an "AS IS" BASIS,
13 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14 * See the License for the specific language governing permissions and
15 * limitations under the License.
16 */
17 package org.apache.commons.pool2.impl;
18
19 import java.io.PrintWriter;
20 import java.io.StringWriter;
21 import java.io.Writer;
22 import java.lang.management.ManagementFactory;
23 import java.lang.ref.WeakReference;
24 import java.lang.reflect.InvocationTargetException;
25 import java.time.Duration;
26 import java.time.Instant;
27 import java.util.ArrayList;
28 import java.util.Arrays;
29 import java.util.Deque;
30 import java.util.Iterator;
31 import java.util.List;
32 import java.util.Map;
33 import java.util.TimerTask;
34 import java.util.concurrent.ScheduledFuture;
35 import java.util.concurrent.atomic.AtomicLong;
36 import java.util.concurrent.atomic.AtomicReference;
37 import java.util.stream.Collectors;
38
39 import javax.management.InstanceAlreadyExistsException;
40 import javax.management.InstanceNotFoundException;
41 import javax.management.MBeanRegistrationException;
42 import javax.management.MBeanServer;
43 import javax.management.MalformedObjectNameException;
44 import javax.management.NotCompliantMBeanException;
45 import javax.management.ObjectName;
46
47 import org.apache.commons.pool2.BaseObject;
48 import org.apache.commons.pool2.PooledObject;
49 import org.apache.commons.pool2.PooledObjectState;
50 import org.apache.commons.pool2.SwallowedExceptionListener;
51
52 /**
53 * Base class that provides common functionality for {@link GenericObjectPool}
54 * and {@link GenericKeyedObjectPool}. The primary reason this class exists is
55 * reduce code duplication between the two pool implementations.
56 * <p>
57 * Concrete implementations of this class are expected to be thread-safe.
58 * </p>
59 *
60 * @param <T> Type of element pooled in this pool.
61 * @since 2.0
62 */
63 public abstract class BaseGenericObjectPool<T> extends BaseObject implements AutoCloseable {
64
65 /**
66 * The idle object eviction iterator. Holds a reference to the idle objects.
67 */
68 final class EvictionIterator implements Iterator<PooledObject<T>> {
69
70 private final Deque<PooledObject<T>> idleObjects;
71 private final Iterator<PooledObject<T>> idleObjectIterator;
72
73 /**
74 * Constructs an EvictionIterator for the provided idle instance deque.
75 * @param idleObjects underlying deque.
76 */
77 EvictionIterator(final Deque<PooledObject<T>> idleObjects) {
78 this.idleObjects = idleObjects;
79
80 if (getLifo()) {
81 idleObjectIterator = idleObjects.descendingIterator();
82 } else {
83 idleObjectIterator = idleObjects.iterator();
84 }
85 }
86
87 /**
88 * Gets the idle object deque referenced by this iterator.
89 * @return the idle object deque
90 */
91 public Deque<PooledObject<T>> getIdleObjects() {
92 return idleObjects;
93 }
94
95 /** {@inheritDoc} */
96 @Override
97 public boolean hasNext() {
98 return idleObjectIterator.hasNext();
99 }
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 }