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