BaseGenericObjectPool.java
- /*
- * Licensed to the Apache Software Foundation (ASF) under one or more
- * contributor license agreements. See the NOTICE file distributed with
- * this work for additional information regarding copyright ownership.
- * The ASF licenses this file to You under the Apache License, Version 2.0
- * (the "License"); you may not use this file except in compliance with
- * the License. You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
- package org.apache.commons.pool2.impl;
- import java.io.PrintWriter;
- import java.io.StringWriter;
- import java.io.Writer;
- import java.lang.management.ManagementFactory;
- import java.lang.ref.WeakReference;
- import java.lang.reflect.InvocationTargetException;
- import java.time.Duration;
- import java.time.Instant;
- import java.util.ArrayList;
- import java.util.Arrays;
- import java.util.Deque;
- import java.util.Iterator;
- import java.util.List;
- import java.util.Map;
- import java.util.TimerTask;
- import java.util.concurrent.ScheduledFuture;
- import java.util.concurrent.atomic.AtomicLong;
- import java.util.concurrent.atomic.AtomicReference;
- import java.util.stream.Collectors;
- import javax.management.InstanceAlreadyExistsException;
- import javax.management.InstanceNotFoundException;
- import javax.management.MBeanRegistrationException;
- import javax.management.MBeanServer;
- import javax.management.MalformedObjectNameException;
- import javax.management.NotCompliantMBeanException;
- import javax.management.ObjectName;
- import org.apache.commons.pool2.BaseObject;
- import org.apache.commons.pool2.PooledObject;
- import org.apache.commons.pool2.PooledObjectState;
- import org.apache.commons.pool2.SwallowedExceptionListener;
- /**
- * Base class that provides common functionality for {@link GenericObjectPool}
- * and {@link GenericKeyedObjectPool}. The primary reason this class exists is
- * reduce code duplication between the two pool implementations.
- * <p>
- * Concrete implementations of this class are expected to be thread-safe.
- * </p>
- *
- * @param <T> Type of element pooled in this pool.
- * @since 2.0
- */
- public abstract class BaseGenericObjectPool<T> extends BaseObject implements AutoCloseable {
- /**
- * The idle object eviction iterator. Holds a reference to the idle objects.
- */
- final class EvictionIterator implements Iterator<PooledObject<T>> {
- private final Deque<PooledObject<T>> idleObjects;
- private final Iterator<PooledObject<T>> idleObjectIterator;
- /**
- * Constructs an EvictionIterator for the provided idle instance deque.
- * @param idleObjects underlying deque.
- */
- EvictionIterator(final Deque<PooledObject<T>> idleObjects) {
- this.idleObjects = idleObjects;
- if (getLifo()) {
- idleObjectIterator = idleObjects.descendingIterator();
- } else {
- idleObjectIterator = idleObjects.iterator();
- }
- }
- /**
- * Gets the idle object deque referenced by this iterator.
- * @return the idle object deque
- */
- public Deque<PooledObject<T>> getIdleObjects() {
- return idleObjects;
- }
- /** {@inheritDoc} */
- @Override
- public boolean hasNext() {
- return idleObjectIterator.hasNext();
- }
- /** {@inheritDoc} */
- @Override
- public PooledObject<T> next() {
- return idleObjectIterator.next();
- }
- /** {@inheritDoc} */
- @Override
- public void remove() {
- idleObjectIterator.remove();
- }
- }
- /**
- * The idle object evictor {@link TimerTask}.
- *
- * @see GenericKeyedObjectPool#setTimeBetweenEvictionRunsMillis
- */
- final class Evictor implements Runnable {
- private ScheduledFuture<?> scheduledFuture;
- /**
- * Cancels the scheduled future.
- */
- void cancel() {
- scheduledFuture.cancel(false);
- }
- BaseGenericObjectPool<T> owner() {
- return BaseGenericObjectPool.this;
- }
- /**
- * Run pool maintenance. Evict objects qualifying for eviction and then
- * ensure that the minimum number of idle instances are available.
- * Since the Timer that invokes Evictors is shared for all Pools but
- * pools may exist in different class loaders, the Evictor ensures that
- * any actions taken are under the class loader of the factory
- * associated with the pool.
- */
- @Override
- public void run() {
- final ClassLoader savedClassLoader = Thread.currentThread().getContextClassLoader();
- try {
- if (factoryClassLoader != null) {
- // Set the class loader for the factory
- final ClassLoader cl = factoryClassLoader.get();
- if (cl == null) {
- // The pool has been dereferenced and the class loader
- // GC'd. Cancel this timer so the pool can be GC'd as
- // well.
- cancel();
- return;
- }
- Thread.currentThread().setContextClassLoader(cl);
- }
- // Evict from the pool
- try {
- evict();
- } catch (final Exception e) {
- swallowException(e);
- } catch (final OutOfMemoryError oome) {
- // Log problem but give evictor thread a chance to continue
- // in case error is recoverable
- oome.printStackTrace(System.err);
- }
- // Re-create idle instances.
- try {
- ensureMinIdle();
- } catch (final Exception e) {
- swallowException(e);
- }
- } finally {
- // Restore the previous CCL
- Thread.currentThread().setContextClassLoader(savedClassLoader);
- }
- }
- /**
- * Sets the scheduled future.
- *
- * @param scheduledFuture the scheduled future.
- */
- void setScheduledFuture(final ScheduledFuture<?> scheduledFuture) {
- this.scheduledFuture = scheduledFuture;
- }
- @Override
- public String toString() {
- return getClass().getName() + " [scheduledFuture=" + scheduledFuture + "]";
- }
- }
- /**
- * Wrapper for objects under management by the pool.
- *
- * GenericObjectPool and GenericKeyedObjectPool maintain references to all
- * objects under management using maps keyed on the objects. This wrapper
- * class ensures that objects can work as hash keys.
- *
- * @param <T> type of objects in the pool
- */
- static class IdentityWrapper<T> {
- /** Wrapped object */
- private final T instance;
- /**
- * Constructs a wrapper for an instance.
- *
- * @param instance object to wrap
- */
- public IdentityWrapper(final T instance) {
- this.instance = instance;
- }
- @Override
- @SuppressWarnings("rawtypes")
- public boolean equals(final Object other) {
- return other instanceof IdentityWrapper && ((IdentityWrapper) other).instance == instance;
- }
- /**
- * @return the wrapped object
- */
- public T getObject() {
- return instance;
- }
- @Override
- public int hashCode() {
- return System.identityHashCode(instance);
- }
- @Override
- public String toString() {
- final StringBuilder builder = new StringBuilder();
- builder.append("IdentityWrapper [instance=");
- builder.append(instance);
- builder.append("]");
- return builder.toString();
- }
- }
- /**
- * Maintains a cache of values for a single metric and reports
- * statistics on the cached values.
- */
- private static final class StatsStore {
- private static final int NONE = -1;
- private final AtomicLong[] values;
- private final int size;
- private int index;
- /**
- * Constructs a new instance with the given cache size.
- *
- * @param size number of values to maintain in the cache.
- */
- StatsStore(final int size) {
- this.size = size;
- this.values = new AtomicLong[size];
- Arrays.setAll(values, i -> new AtomicLong(NONE));
- }
- void add(final Duration value) {
- add(value.toMillis());
- }
- /**
- * Adds a value to the cache. If the cache is full, one of the
- * existing values is replaced by the new value.
- *
- * @param value new value to add to the cache.
- */
- synchronized void add(final long value) {
- values[index].set(value);
- index++;
- if (index == size) {
- index = 0;
- }
- }
- /**
- * Gets the mean of the cached values.
- *
- * @return the mean of the cache, truncated to long
- */
- public long getMean() {
- double result = 0;
- int counter = 0;
- for (int i = 0; i < size; i++) {
- final long value = values[i].get();
- if (value != NONE) {
- counter++;
- result = result * ((counter - 1) / (double) counter) + value / (double) counter;
- }
- }
- return (long) result;
- }
- /**
- * Gets the mean Duration of the cached values.
- *
- * @return the mean Duration of the cache, truncated to long milliseconds of a Duration.
- */
- Duration getMeanDuration() {
- return Duration.ofMillis(getMean());
- }
- /**
- * Gets the current values as a List.
- *
- * @return the current values as a List.
- */
- synchronized List<AtomicLong> getValues() {
- return Arrays.stream(values, 0, index).collect(Collectors.toList());
- }
- @Override
- public String toString() {
- final StringBuilder builder = new StringBuilder();
- builder.append("StatsStore [");
- // Only append what's been filled in.
- builder.append(getValues());
- builder.append("], size=");
- builder.append(size);
- builder.append(", index=");
- builder.append(index);
- builder.append("]");
- return builder.toString();
- }
- }
- // Constants
- /**
- * The size of the caches used to store historical data for some attributes
- * so that rolling means may be calculated.
- */
- public static final int MEAN_TIMING_STATS_CACHE_SIZE = 100;
- private static final String EVICTION_POLICY_TYPE_NAME = EvictionPolicy.class.getName();
- private static final Duration DEFAULT_REMOVE_ABANDONED_TIMEOUT = Duration.ofSeconds(Integer.MAX_VALUE);
- // Configuration attributes
- private volatile int maxTotal = GenericKeyedObjectPoolConfig.DEFAULT_MAX_TOTAL;
- private volatile boolean blockWhenExhausted = BaseObjectPoolConfig.DEFAULT_BLOCK_WHEN_EXHAUSTED;
- private volatile Duration maxWaitDuration = BaseObjectPoolConfig.DEFAULT_MAX_WAIT;
- private volatile boolean lifo = BaseObjectPoolConfig.DEFAULT_LIFO;
- private final boolean fairness;
- private volatile boolean testOnCreate = BaseObjectPoolConfig.DEFAULT_TEST_ON_CREATE;
- private volatile boolean testOnBorrow = BaseObjectPoolConfig.DEFAULT_TEST_ON_BORROW;
- private volatile boolean testOnReturn = BaseObjectPoolConfig.DEFAULT_TEST_ON_RETURN;
- private volatile boolean testWhileIdle = BaseObjectPoolConfig.DEFAULT_TEST_WHILE_IDLE;
- private volatile Duration durationBetweenEvictionRuns = BaseObjectPoolConfig.DEFAULT_DURATION_BETWEEN_EVICTION_RUNS;
- private volatile int numTestsPerEvictionRun = BaseObjectPoolConfig.DEFAULT_NUM_TESTS_PER_EVICTION_RUN;
- private volatile Duration minEvictableIdleDuration = BaseObjectPoolConfig.DEFAULT_MIN_EVICTABLE_IDLE_DURATION;
- private volatile Duration softMinEvictableIdleDuration = BaseObjectPoolConfig.DEFAULT_SOFT_MIN_EVICTABLE_IDLE_DURATION;
- private volatile EvictionPolicy<T> evictionPolicy;
- private volatile Duration evictorShutdownTimeoutDuration = BaseObjectPoolConfig.DEFAULT_EVICTOR_SHUTDOWN_TIMEOUT;
- // Internal (primarily state) attributes
- final Object closeLock = new Object();
- volatile boolean closed;
- final Object evictionLock = new Object();
- private Evictor evictor; // @GuardedBy("evictionLock")
- EvictionIterator evictionIterator; // @GuardedBy("evictionLock")
- /**
- * Class loader for evictor thread to use since, in a JavaEE or similar
- * environment, the context class loader for the evictor thread may not have
- * visibility of the correct factory. See POOL-161. Uses a weak reference to
- * avoid potential memory leaks if the Pool is discarded rather than closed.
- */
- private final WeakReference<ClassLoader> factoryClassLoader;
- // Monitoring (primarily JMX) attributes
- private final ObjectName objectName;
- private final String creationStackTrace;
- private final AtomicLong borrowedCount = new AtomicLong();
- private final AtomicLong returnedCount = new AtomicLong();
- final AtomicLong createdCount = new AtomicLong();
- final AtomicLong destroyedCount = new AtomicLong();
- final AtomicLong destroyedByEvictorCount = new AtomicLong();
- final AtomicLong destroyedByBorrowValidationCount = new AtomicLong();
- private final StatsStore activeTimes = new StatsStore(MEAN_TIMING_STATS_CACHE_SIZE);
- private final StatsStore idleTimes = new StatsStore(MEAN_TIMING_STATS_CACHE_SIZE);
- private final StatsStore waitTimes = new StatsStore(MEAN_TIMING_STATS_CACHE_SIZE);
- private final AtomicReference<Duration> maxBorrowWaitDuration = new AtomicReference<>(Duration.ZERO);
- private volatile SwallowedExceptionListener swallowedExceptionListener;
- private volatile boolean messageStatistics;
- /** Additional configuration properties for abandoned object tracking. */
- protected volatile AbandonedConfig abandonedConfig;
- /**
- * Handles JMX registration (if required) and the initialization required for
- * monitoring.
- *
- * @param config Pool configuration
- * @param jmxNameBase The default base JMX name for the new pool unless
- * overridden by the config
- * @param jmxNamePrefix Prefix to be used for JMX name for the new pool
- */
- public BaseGenericObjectPool(final BaseObjectPoolConfig<T> config,
- final String jmxNameBase, final String jmxNamePrefix) {
- if (config.getJmxEnabled()) {
- this.objectName = jmxRegister(config, jmxNameBase, jmxNamePrefix);
- } else {
- this.objectName = null;
- }
- // Populate the creation stack trace
- this.creationStackTrace = getStackTrace(new Exception());
- // save the current TCCL (if any) to be used later by the evictor Thread
- final ClassLoader cl = Thread.currentThread().getContextClassLoader();
- if (cl == null) {
- factoryClassLoader = null;
- } else {
- factoryClassLoader = new WeakReference<>(cl);
- }
- fairness = config.getFairness();
- }
- /**
- * Appends statistics if enabled.
- * <p>
- * 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
- * information.
- * </p>
- *
- * @param string The root string.
- * @return The root string plus statistics.
- */
- String appendStats(final String string) {
- return messageStatistics ? string + ", " + getStatsString() : string;
- }
- /**
- * Verifies that the pool is open.
- * @throws IllegalStateException if the pool is closed.
- */
- final void assertOpen() throws IllegalStateException {
- if (isClosed()) {
- throw new IllegalStateException("Pool not open");
- }
- }
- /**
- * Closes the pool, destroys the remaining idle objects and, if registered
- * in JMX, deregisters it.
- */
- @Override
- public abstract void close();
- /**
- * Creates a list of pooled objects to remove based on their state.
- * @param abandonedConfig The abandoned configuration.
- * @param allObjects PooledObject instances to consider.
- * @return a list of pooled objects to remove based on their state.
- */
- ArrayList<PooledObject<T>> createRemoveList(final AbandonedConfig abandonedConfig, final Map<IdentityWrapper<T>, PooledObject<T>> allObjects) {
- final Instant timeout = Instant.now().minus(abandonedConfig.getRemoveAbandonedTimeoutDuration());
- final ArrayList<PooledObject<T>> remove = new ArrayList<>();
- allObjects.values().forEach(pooledObject -> {
- synchronized (pooledObject) {
- if (pooledObject.getState() == PooledObjectState.ALLOCATED &&
- pooledObject.getLastUsedInstant().compareTo(timeout) <= 0) {
- pooledObject.markAbandoned();
- remove.add(pooledObject);
- }
- }
- });
- return remove;
- }
- /**
- * Tries to ensure that the configured minimum number of idle instances are
- * available in the pool.
- * @throws Exception if an error occurs creating idle instances
- */
- abstract void ensureMinIdle() throws Exception;
- /**
- * Perform {@code numTests} idle object eviction tests, evicting
- * examined objects that meet the criteria for eviction. If
- * {@code testWhileIdle} is true, examined objects are validated
- * when visited (and removed if invalid); otherwise only objects that
- * have been idle for more than {@code minEvicableIdleTimeMillis}
- * are removed.
- *
- * @throws Exception when there is a problem evicting idle objects.
- */
- public abstract void evict() throws Exception;
- /**
- * Gets whether to block when the {@code borrowObject()} method is
- * invoked when the pool is exhausted (the maximum number of "active"
- * objects has been reached).
- *
- * @return {@code true} if {@code borrowObject()} should block
- * when the pool is exhausted
- *
- * @see #setBlockWhenExhausted
- */
- public final boolean getBlockWhenExhausted() {
- return blockWhenExhausted;
- }
- /**
- * Gets the total number of objects successfully borrowed from this pool over the
- * lifetime of the pool.
- * @return the borrowed object count
- */
- public final long getBorrowedCount() {
- return borrowedCount.get();
- }
- /**
- * Gets the total number of objects created for this pool over the lifetime of
- * the pool.
- * @return the created object count
- */
- public final long getCreatedCount() {
- return createdCount.get();
- }
- /**
- * Gets the stack trace for the call that created this pool. JMX
- * registration may trigger a memory leak so it is important that pools are
- * deregistered when no longer used by calling the {@link #close()} method.
- * This method is provided to assist with identifying code that creates but
- * does not close it thereby creating a memory leak.
- * @return pool creation stack trace
- */
- public final String getCreationStackTrace() {
- return creationStackTrace;
- }
- /**
- * Gets the total number of objects destroyed by this pool as a result of failing
- * validation during {@code borrowObject()} over the lifetime of the
- * pool.
- * @return validation destroyed object count
- */
- public final long getDestroyedByBorrowValidationCount() {
- return destroyedByBorrowValidationCount.get();
- }
- /**
- * Gets the total number of objects destroyed by the evictor associated with this
- * pool over the lifetime of the pool.
- * @return the evictor destroyed object count
- */
- public final long getDestroyedByEvictorCount() {
- return destroyedByEvictorCount.get();
- }
- /**
- * Gets the total number of objects destroyed by this pool over the lifetime of
- * the pool.
- * @return the destroyed object count
- */
- public final long getDestroyedCount() {
- return destroyedCount.get();
- }
- /**
- * Gets the duration to sleep between runs of the idle
- * object evictor thread. When non-positive, no idle object evictor thread
- * will be run.
- *
- * @return number of milliseconds to sleep between evictor runs
- * @see #setTimeBetweenEvictionRuns
- * @since 2.11.0
- */
- public final Duration getDurationBetweenEvictionRuns() {
- return durationBetweenEvictionRuns;
- }
- /**
- * Gets the {@link EvictionPolicy} defined for this pool.
- *
- * @return the eviction policy
- * @since 2.4
- * @since 2.6.0 Changed access from protected to public.
- */
- public EvictionPolicy<T> getEvictionPolicy() {
- return evictionPolicy;
- }
- /**
- * Gets the name of the {@link EvictionPolicy} implementation that is
- * used by this pool.
- *
- * @return The fully qualified class name of the {@link EvictionPolicy}
- * @see #setEvictionPolicyClassName(String)
- */
- public final String getEvictionPolicyClassName() {
- return evictionPolicy.getClass().getName();
- }
- /**
- * Gets the timeout that will be used when waiting for the Evictor to
- * shutdown if this pool is closed and it is the only pool still using the
- * the value for the Evictor.
- *
- * @return The timeout that will be used while waiting for
- * the Evictor to shut down.
- * @since 2.10.0
- * @deprecated Use {@link #getEvictorShutdownTimeoutDuration()}.
- */
- @Deprecated
- public final Duration getEvictorShutdownTimeout() {
- return evictorShutdownTimeoutDuration;
- }
- /**
- * Gets the timeout that will be used when waiting for the Evictor to
- * shutdown if this pool is closed and it is the only pool still using the
- * the value for the Evictor.
- *
- * @return The timeout that will be used while waiting for
- * the Evictor to shut down.
- * @since 2.11.0
- */
- public final Duration getEvictorShutdownTimeoutDuration() {
- return evictorShutdownTimeoutDuration;
- }
- /**
- * Gets the timeout that will be used when waiting for the Evictor to
- * shutdown if this pool is closed and it is the only pool still using the
- * the value for the Evictor.
- *
- * @return The timeout in milliseconds that will be used while waiting for
- * the Evictor to shut down.
- * @deprecated Use {@link #getEvictorShutdownTimeoutDuration()}.
- */
- @Deprecated
- public final long getEvictorShutdownTimeoutMillis() {
- return evictorShutdownTimeoutDuration.toMillis();
- }
- /**
- * Gets whether or not the pool serves threads waiting to borrow objects fairly.
- * True means that waiting threads are served as if waiting in a FIFO queue.
- *
- * @return {@code true} if waiting threads are to be served
- * by the pool in arrival order
- */
- public final boolean getFairness() {
- return fairness;
- }
- /**
- * Gets the name under which the pool has been registered with the
- * platform MBean server or {@code null} if the pool has not been
- * registered.
- * @return the JMX name
- */
- public final ObjectName getJmxName() {
- return objectName;
- }
- /**
- * Gets whether the pool has LIFO (last in, first out) behavior with
- * respect to idle objects - always returning the most recently used object
- * from the pool, or as a FIFO (first in, first out) queue, where the pool
- * always returns the oldest object in the idle object pool.
- *
- * @return {@code true} if the pool is configured with LIFO behavior
- * or {@code false} if the pool is configured with FIFO
- * behavior
- *
- * @see #setLifo
- */
- public final boolean getLifo() {
- return lifo;
- }
- /**
- * Gets whether this pool identifies and logs any abandoned objects.
- *
- * @return {@code true} if abandoned object removal is configured for this
- * pool and removal events are to be logged otherwise {@code false}
- *
- * @see AbandonedConfig#getLogAbandoned()
- * @since 2.11.0
- */
- public boolean getLogAbandoned() {
- final AbandonedConfig ac = this.abandonedConfig;
- return ac != null && ac.getLogAbandoned();
- }
- /**
- * Gets the maximum time a thread has waited to borrow objects from the pool.
- *
- * @return maximum wait time in milliseconds since the pool was created
- * @since 2.12.0
- */
- public final Duration getMaxBorrowWaitDuration() {
- return maxBorrowWaitDuration.get();
- }
- /**
- * Gets the maximum time a thread has waited to borrow objects from the pool.
- *
- * @return maximum wait time in milliseconds since the pool was created
- * @deprecated Use {@link #getMaxBorrowWaitDuration()}.
- */
- @Deprecated
- public final long getMaxBorrowWaitTimeMillis() {
- return maxBorrowWaitDuration.get().toMillis();
- }
- /**
- * Gets the maximum number of objects that can be allocated by the pool
- * (checked out to clients, or idle awaiting checkout) at a given time. When
- * negative, there is no limit to the number of objects that can be
- * managed by the pool at one time.
- *
- * @return the cap on the total number of object instances managed by the
- * pool.
- * @see #setMaxTotal
- */
- public final int getMaxTotal() {
- return maxTotal;
- }
- /**
- * Gets the maximum duration the
- * {@code borrowObject()} method should block before throwing an
- * exception when the pool is exhausted and
- * {@link #getBlockWhenExhausted} is true. When less than 0, the
- * {@code borrowObject()} method may block indefinitely.
- *
- * @return the maximum number of milliseconds {@code borrowObject()}
- * will block.
- *
- * @see #setMaxWait
- * @see #setBlockWhenExhausted
- * @since 2.11.0
- */
- public final Duration getMaxWaitDuration() {
- return maxWaitDuration;
- }
- /**
- * Gets the maximum amount of time (in milliseconds) the
- * {@code borrowObject()} method should block before throwing an
- * exception when the pool is exhausted and
- * {@link #getBlockWhenExhausted} is true. When less than 0, the
- * {@code borrowObject()} method may block indefinitely.
- *
- * @return the maximum number of milliseconds {@code borrowObject()}
- * will block.
- *
- * @see #setMaxWait
- * @see #setBlockWhenExhausted
- * @deprecated Use {@link #getMaxWaitDuration()}.
- */
- @Deprecated
- public final long getMaxWaitMillis() {
- return maxWaitDuration.toMillis();
- }
- /**
- * Gets the mean time objects are active for based on the last {@link
- * #MEAN_TIMING_STATS_CACHE_SIZE} objects returned to the pool.
- * @return mean time an object has been checked out from the pool among
- * recently returned objects.
- *
- * @since 2.12.0
- */
- public final Duration getMeanActiveDuration() {
- return activeTimes.getMeanDuration();
- }
- /**
- * Gets the mean time objects are active for based on the last {@link
- * #MEAN_TIMING_STATS_CACHE_SIZE} objects returned to the pool.
- * @return mean time an object has been checked out from the pool among
- * recently returned objects.
- *
- * @deprecated Use {@link #getMeanActiveDuration()}.
- */
- @Deprecated
- public final long getMeanActiveTimeMillis() {
- return activeTimes.getMean();
- }
- /**
- * Gets the mean time threads wait to borrow an object based on the last {@link
- * #MEAN_TIMING_STATS_CACHE_SIZE} objects borrowed from the pool.
- *
- * @return mean time in milliseconds that a recently served thread has had
- * to wait to borrow an object from the pool.
- * @since 2.12.0
- */
- public final Duration getMeanBorrowWaitDuration() {
- return waitTimes.getMeanDuration();
- }
- /**
- * Gets the mean time threads wait to borrow an object based on the last {@link
- * #MEAN_TIMING_STATS_CACHE_SIZE} objects borrowed from the pool.
- *
- * @return mean time in milliseconds that a recently served thread has had
- * to wait to borrow an object from the pool.
- * @deprecated Use {@link #getMeanBorrowWaitDuration()}.
- */
- @Deprecated
- public final long getMeanBorrowWaitTimeMillis() {
- return waitTimes.getMean();
- }
- /**
- * Gets the mean time objects are idle for based on the last {@link
- * #MEAN_TIMING_STATS_CACHE_SIZE} objects borrowed from the pool.
- *
- * @return mean time an object has been idle in the pool among recently
- * borrowed objects.
- * @since 2.12.0
- */
- public final Duration getMeanIdleDuration() {
- return idleTimes.getMeanDuration();
- }
- /**
- * Gets the mean time objects are idle for based on the last {@link
- * #MEAN_TIMING_STATS_CACHE_SIZE} objects borrowed from the pool.
- *
- * @return mean time an object has been idle in the pool among recently
- * borrowed objects.
- * @deprecated Use {@link #getMeanIdleDuration()}.
- */
- @Deprecated
- public final long getMeanIdleTimeMillis() {
- return idleTimes.getMean();
- }
- /**
- * Gets whether to include statistics in exception messages.
- * <p>
- * 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
- * information.
- * </p>
- *
- * @return whether to include statistics in exception messages.
- * @since 2.11.0
- */
- public boolean getMessageStatistics() {
- return messageStatistics;
- }
- /**
- * Gets the minimum amount of time an object may sit idle in the pool
- * before it is eligible for eviction by the idle object evictor (if any -
- * see {@link #setDurationBetweenEvictionRuns(Duration)}). When non-positive,
- * no objects will be evicted from the pool due to idle time alone.
- *
- * @return minimum amount of time an object may sit idle in the pool before
- * it is eligible for eviction
- *
- * @see #setMinEvictableIdleTimeMillis
- * @see #setTimeBetweenEvictionRunsMillis
- * @since 2.11.0
- */
- public final Duration getMinEvictableIdleDuration() {
- return minEvictableIdleDuration;
- }
- /**
- * Gets the minimum amount of time an object may sit idle in the pool
- * before it is eligible for eviction by the idle object evictor (if any -
- * see {@link #setDurationBetweenEvictionRuns(Duration)}). When non-positive,
- * no objects will be evicted from the pool due to idle time alone.
- *
- * @return minimum amount of time an object may sit idle in the pool before
- * it is eligible for eviction
- *
- * @see #setMinEvictableIdleTimeMillis
- * @see #setTimeBetweenEvictionRunsMillis
- * @since 2.10.0
- * @deprecated Use {@link #getMinEvictableIdleDuration()}.
- */
- @Deprecated
- public final Duration getMinEvictableIdleTime() {
- return minEvictableIdleDuration;
- }
- /**
- * Gets the minimum amount of time an object may sit idle in the pool
- * before it is eligible for eviction by the idle object evictor (if any -
- * see {@link #setTimeBetweenEvictionRunsMillis(long)}). When non-positive,
- * no objects will be evicted from the pool due to idle time alone.
- *
- * @return minimum amount of time an object may sit idle in the pool before
- * it is eligible for eviction
- *
- * @see #setMinEvictableIdleTimeMillis
- * @see #setTimeBetweenEvictionRunsMillis
- * @deprecated Use {@link #getMinEvictableIdleDuration()}.
- */
- @Deprecated
- public final long getMinEvictableIdleTimeMillis() {
- return minEvictableIdleDuration.toMillis();
- }
- /**
- * Gets the number of instances currently idle in this pool.
- * @return count of instances available for checkout from the pool
- */
- public abstract int getNumIdle();
- /**
- * Gets the maximum number of objects to examine during each run (if any)
- * of the idle object evictor thread. When positive, the number of tests
- * performed for a run will be the minimum of the configured value and the
- * number of idle instances in the pool. When negative, the number of tests
- * performed will be <code>ceil({@link #getNumIdle}/
- * abs({@link #getNumTestsPerEvictionRun}))</code> which means that when the
- * value is {@code -n} roughly one nth of the idle objects will be
- * tested per run.
- *
- * @return max number of objects to examine during each evictor run
- * @see #setNumTestsPerEvictionRun
- * @see #setTimeBetweenEvictionRunsMillis
- */
- public final int getNumTestsPerEvictionRun() {
- return numTestsPerEvictionRun;
- }
- /**
- * Gets whether a check is made for abandoned objects when an object is borrowed
- * from this pool.
- *
- * @return {@code true} if abandoned object removal is configured to be
- * activated by borrowObject otherwise {@code false}
- *
- * @see AbandonedConfig#getRemoveAbandonedOnBorrow()
- * @since 2.11.0
- */
- public boolean getRemoveAbandonedOnBorrow() {
- final AbandonedConfig ac = this.abandonedConfig;
- return ac != null && ac.getRemoveAbandonedOnBorrow();
- }
- /**
- * Gets whether a check is made for abandoned objects when the evictor runs.
- *
- * @return {@code true} if abandoned object removal is configured to be
- * activated when the evictor runs otherwise {@code false}
- *
- * @see AbandonedConfig#getRemoveAbandonedOnMaintenance()
- * @since 2.11.0
- */
- public boolean getRemoveAbandonedOnMaintenance() {
- final AbandonedConfig ac = this.abandonedConfig;
- return ac != null && ac.getRemoveAbandonedOnMaintenance();
- }
- /**
- * Gets the timeout before which an object will be considered to be
- * abandoned by this pool.
- *
- * @return The abandoned object timeout in seconds if abandoned object
- * removal is configured for this pool; Integer.MAX_VALUE otherwise.
- *
- * @see AbandonedConfig#getRemoveAbandonedTimeoutDuration()
- * @see AbandonedConfig#getRemoveAbandonedTimeoutDuration()
- * @deprecated Use {@link #getRemoveAbandonedTimeoutDuration()}.
- * @since 2.11.0
- */
- @Deprecated
- public int getRemoveAbandonedTimeout() {
- return (int) getRemoveAbandonedTimeoutDuration().getSeconds();
- }
- /**
- * Gets the timeout before which an object will be considered to be
- * abandoned by this pool.
- *
- * @return The abandoned object timeout in seconds if abandoned object
- * removal is configured for this pool; Integer.MAX_VALUE otherwise.
- *
- * @see AbandonedConfig#getRemoveAbandonedTimeoutDuration()
- * @since 2.11.0
- */
- public Duration getRemoveAbandonedTimeoutDuration() {
- final AbandonedConfig ac = this.abandonedConfig;
- return ac != null ? ac.getRemoveAbandonedTimeoutDuration() : DEFAULT_REMOVE_ABANDONED_TIMEOUT;
- }
- /**
- * Gets the total number of objects returned to this pool over the lifetime of
- * the pool. This excludes attempts to return the same object multiple
- * times.
- * @return the returned object count
- */
- public final long getReturnedCount() {
- return returnedCount.get();
- }
- /**
- * Gets the minimum amount of time an object may sit idle in the pool
- * before it is eligible for eviction by the idle object evictor (if any -
- * see {@link #setDurationBetweenEvictionRuns(Duration)}),
- * with the extra condition that at least {@code minIdle} object
- * instances remain in the pool. This setting is overridden by
- * {@link #getMinEvictableIdleTime} (that is, if
- * {@link #getMinEvictableIdleTime} is positive, then
- * {@link #getSoftMinEvictableIdleTime} is ignored).
- *
- * @return minimum amount of time an object may sit idle in the pool before
- * it is eligible for eviction if minIdle instances are available
- *
- * @see #setSoftMinEvictableIdleDuration(Duration)
- * @since 2.11.0
- */
- public final Duration getSoftMinEvictableIdleDuration() {
- return softMinEvictableIdleDuration;
- }
- /**
- * Gets the minimum amount of time an object may sit idle in the pool
- * before it is eligible for eviction by the idle object evictor (if any -
- * see {@link #setDurationBetweenEvictionRuns(Duration)}),
- * with the extra condition that at least {@code minIdle} object
- * instances remain in the pool. This setting is overridden by
- * {@link #getMinEvictableIdleTime} (that is, if
- * {@link #getMinEvictableIdleTime} is positive, then
- * {@link #getSoftMinEvictableIdleTime} is ignored).
- *
- * @return minimum amount of time an object may sit idle in the pool before
- * it is eligible for eviction if minIdle instances are available
- *
- * @see #setSoftMinEvictableIdleDuration(Duration)
- * @since 2.10.0
- * @deprecated Use {@link #getSoftMinEvictableIdleDuration}.
- */
- @Deprecated
- public final Duration getSoftMinEvictableIdleTime() {
- return softMinEvictableIdleDuration;
- }
- /**
- * Gets the minimum amount of time an object may sit idle in the pool
- * before it is eligible for eviction by the idle object evictor (if any -
- * see {@link #setTimeBetweenEvictionRunsMillis(long)}),
- * with the extra condition that at least {@code minIdle} object
- * instances remain in the pool. This setting is overridden by
- * {@link #getMinEvictableIdleTimeMillis} (that is, if
- * {@link #getMinEvictableIdleTimeMillis} is positive, then
- * {@link #getSoftMinEvictableIdleTimeMillis} is ignored).
- *
- * @return minimum amount of time an object may sit idle in the pool before
- * it is eligible for eviction if minIdle instances are available
- *
- * @see #setSoftMinEvictableIdleTimeMillis
- * @deprecated Use {@link #getSoftMinEvictableIdleTime()}.
- */
- @Deprecated
- public final long getSoftMinEvictableIdleTimeMillis() {
- return softMinEvictableIdleDuration.toMillis();
- }
- /**
- * Gets the stack trace of an exception as a string.
- * @param e exception to trace
- * @return exception stack trace as a string
- */
- private String getStackTrace(final Exception e) {
- // Need the exception in string form to prevent the retention of
- // references to classes in the stack trace that could trigger a memory
- // leak in a container environment.
- final Writer w = new StringWriter();
- final PrintWriter pw = new PrintWriter(w);
- e.printStackTrace(pw);
- return w.toString();
- }
- /**
- * Gets a statistics string.
- *
- * @return a statistics string.
- */
- String getStatsString() {
- // Simply listed in AB order.
- return String.format(
- "activeTimes=%s, blockWhenExhausted=%s, borrowedCount=%,d, closed=%s, createdCount=%,d, destroyedByBorrowValidationCount=%,d, " +
- "destroyedByEvictorCount=%,d, evictorShutdownTimeoutDuration=%s, fairness=%s, idleTimes=%s, lifo=%s, maxBorrowWaitDuration=%s, " +
- "maxTotal=%s, maxWaitDuration=%s, minEvictableIdleDuration=%s, numTestsPerEvictionRun=%s, returnedCount=%s, " +
- "softMinEvictableIdleDuration=%s, testOnBorrow=%s, testOnCreate=%s, testOnReturn=%s, testWhileIdle=%s, " +
- "durationBetweenEvictionRuns=%s, waitTimes=%s",
- activeTimes.getValues(), blockWhenExhausted, borrowedCount.get(), closed, createdCount.get(), destroyedByBorrowValidationCount.get(),
- destroyedByEvictorCount.get(), evictorShutdownTimeoutDuration, fairness, idleTimes.getValues(), lifo, maxBorrowWaitDuration.get(),
- maxTotal, maxWaitDuration, minEvictableIdleDuration, numTestsPerEvictionRun, returnedCount, softMinEvictableIdleDuration, testOnBorrow,
- testOnCreate, testOnReturn, testWhileIdle, durationBetweenEvictionRuns, waitTimes.getValues());
- }
- /**
- * Gets the listener used (if any) to receive notifications of exceptions
- * unavoidably swallowed by the pool.
- *
- * @return The listener or {@code null} for no listener
- */
- public final SwallowedExceptionListener getSwallowedExceptionListener() {
- return swallowedExceptionListener;
- }
- /**
- * Gets whether objects borrowed from the pool will be validated before
- * being returned from the {@code borrowObject()} method. Validation is
- * performed by the {@code validateObject()} method of the factory
- * associated with the pool. If the object fails to validate, it will be
- * removed from the pool and destroyed, and a new attempt will be made to
- * borrow an object from the pool.
- *
- * @return {@code true} if objects are validated before being returned
- * from the {@code borrowObject()} method
- *
- * @see #setTestOnBorrow
- */
- public final boolean getTestOnBorrow() {
- return testOnBorrow;
- }
- /**
- * Gets whether objects created for the pool will be validated before
- * being returned from the {@code borrowObject()} method. Validation is
- * performed by the {@code validateObject()} method of the factory
- * associated with the pool. If the object fails to validate, then
- * {@code borrowObject()} will fail.
- *
- * @return {@code true} if newly created objects are validated before
- * being returned from the {@code borrowObject()} method
- *
- * @see #setTestOnCreate
- * @since 2.2
- */
- public final boolean getTestOnCreate() {
- return testOnCreate;
- }
- /**
- * Gets whether objects borrowed from the pool will be validated when
- * they are returned to the pool via the {@code returnObject()} method.
- * Validation is performed by the {@code validateObject()} method of
- * the factory associated with the pool. Returning objects that fail validation
- * are destroyed rather then being returned the pool.
- *
- * @return {@code true} if objects are validated on return to
- * the pool via the {@code returnObject()} method
- *
- * @see #setTestOnReturn
- */
- public final boolean getTestOnReturn() {
- return testOnReturn;
- }
- /**
- * Gets whether objects sitting idle in the pool will be validated by the
- * idle object evictor (if any - see
- * {@link #setDurationBetweenEvictionRuns(Duration)}). Validation is performed
- * by the {@code validateObject()} method of the factory associated
- * with the pool. If the object fails to validate, it will be removed from
- * the pool and destroyed.
- *
- * @return {@code true} if objects will be validated by the evictor
- * @see #setTestWhileIdle
- * @see #setTimeBetweenEvictionRunsMillis
- */
- public final boolean getTestWhileIdle() {
- return testWhileIdle;
- }
- /**
- * Gets the duration to sleep between runs of the idle
- * object evictor thread. When non-positive, no idle object evictor thread
- * will be run.
- *
- * @return number of milliseconds to sleep between evictor runs
- * @see #setTimeBetweenEvictionRuns
- * @since 2.10.0
- * @deprecated {@link #getDurationBetweenEvictionRuns()}.
- */
- @Deprecated
- public final Duration getTimeBetweenEvictionRuns() {
- return durationBetweenEvictionRuns;
- }
- /**
- * Gets the number of milliseconds to sleep between runs of the idle
- * object evictor thread. When non-positive, no idle object evictor thread
- * will be run.
- *
- * @return number of milliseconds to sleep between evictor runs
- * @see #setTimeBetweenEvictionRunsMillis
- * @deprecated Use {@link #getDurationBetweenEvictionRuns()}.
- */
- @Deprecated
- public final long getTimeBetweenEvictionRunsMillis() {
- return durationBetweenEvictionRuns.toMillis();
- }
- /**
- * Tests whether or not abandoned object removal is configured for this pool.
- *
- * @return true if this pool is configured to detect and remove
- * abandoned objects
- * @since 2.11.0
- */
- public boolean isAbandonedConfig() {
- return abandonedConfig != null;
- }
- /**
- * Tests whether this pool instance been closed.
- * @return {@code true} when this pool has been closed.
- */
- public final boolean isClosed() {
- return closed;
- }
- /**
- * Registers the pool with the platform MBean server.
- * The registered name will be
- * {@code jmxNameBase + jmxNamePrefix + i} where i is the least
- * integer greater than or equal to 1 such that the name is not already
- * registered. Swallows MBeanRegistrationException, NotCompliantMBeanException
- * returning null.
- *
- * @param config Pool configuration
- * @param jmxNameBase default base JMX name for this pool
- * @param jmxNamePrefix name prefix
- * @return registered ObjectName, null if registration fails
- */
- private ObjectName jmxRegister(final BaseObjectPoolConfig<T> config,
- final String jmxNameBase, String jmxNamePrefix) {
- ObjectName newObjectName = null;
- final MBeanServer mbs = ManagementFactory.getPlatformMBeanServer();
- int i = 1;
- boolean registered = false;
- String base = config.getJmxNameBase();
- if (base == null) {
- base = jmxNameBase;
- }
- while (!registered) {
- try {
- ObjectName objName;
- // Skip the numeric suffix for the first pool in case there is
- // only one so the names are cleaner.
- if (i == 1) {
- objName = new ObjectName(base + jmxNamePrefix);
- } else {
- objName = new ObjectName(base + jmxNamePrefix + i);
- }
- if (!mbs.isRegistered(objName)) {
- mbs.registerMBean(this, objName);
- newObjectName = objName;
- registered = true;
- } else {
- // Increment the index and try again
- i++;
- }
- } catch (final MalformedObjectNameException e) {
- if (BaseObjectPoolConfig.DEFAULT_JMX_NAME_PREFIX.equals(
- jmxNamePrefix) && jmxNameBase.equals(base)) {
- // Shouldn't happen. Skip registration if it does.
- registered = true;
- } else {
- // Must be an invalid name. Use the defaults instead.
- jmxNamePrefix =
- BaseObjectPoolConfig.DEFAULT_JMX_NAME_PREFIX;
- base = jmxNameBase;
- }
- } catch (final InstanceAlreadyExistsException e) {
- // Increment the index and try again
- i++;
- } catch (final MBeanRegistrationException | NotCompliantMBeanException e) {
- // Shouldn't happen. Skip registration if it does.
- registered = true;
- }
- }
- return newObjectName;
- }
- /**
- * Unregisters this pool's MBean.
- */
- final void jmxUnregister() {
- if (objectName != null) {
- try {
- ManagementFactory.getPlatformMBeanServer().unregisterMBean(objectName);
- } catch (final MBeanRegistrationException | InstanceNotFoundException e) {
- swallowException(e);
- }
- }
- }
- /**
- * Marks the object as returning to the pool.
- * @param pooledObject instance to return to the keyed pool
- */
- protected void markReturningState(final PooledObject<T> pooledObject) {
- synchronized (pooledObject) {
- if (pooledObject.getState() != PooledObjectState.ALLOCATED) {
- throw new IllegalStateException("Object has already been returned to this pool or is invalid");
- }
- pooledObject.markReturning(); // Keep from being marked abandoned
- }
- }
- /**
- * Sets the abandoned object removal configuration.
- *
- * @param abandonedConfig the new configuration to use. This is used by value.
- * @see AbandonedConfig
- * @since 2.11.0
- */
- public void setAbandonedConfig(final AbandonedConfig abandonedConfig) {
- this.abandonedConfig = AbandonedConfig.copy(abandonedConfig);
- }
- /**
- * Sets whether to block when the {@code borrowObject()} method is
- * invoked when the pool is exhausted (the maximum number of "active"
- * objects has been reached).
- *
- * @param blockWhenExhausted {@code true} if
- * {@code borrowObject()} should block
- * when the pool is exhausted
- *
- * @see #getBlockWhenExhausted
- */
- public final void setBlockWhenExhausted(final boolean blockWhenExhausted) {
- this.blockWhenExhausted = blockWhenExhausted;
- }
- /**
- * Sets the receiver with the given configuration.
- *
- * @param config Initialization source.
- */
- protected void setConfig(final BaseObjectPoolConfig<T> config) {
- setLifo(config.getLifo());
- setMaxWait(config.getMaxWaitDuration());
- setBlockWhenExhausted(config.getBlockWhenExhausted());
- setTestOnCreate(config.getTestOnCreate());
- setTestOnBorrow(config.getTestOnBorrow());
- setTestOnReturn(config.getTestOnReturn());
- setTestWhileIdle(config.getTestWhileIdle());
- setNumTestsPerEvictionRun(config.getNumTestsPerEvictionRun());
- setMinEvictableIdleDuration(config.getMinEvictableIdleDuration());
- setDurationBetweenEvictionRuns(config.getDurationBetweenEvictionRuns());
- setSoftMinEvictableIdleDuration(config.getSoftMinEvictableIdleDuration());
- final EvictionPolicy<T> policy = config.getEvictionPolicy();
- if (policy == null) {
- // Use the class name (pre-2.6.0 compatible)
- setEvictionPolicyClassName(config.getEvictionPolicyClassName());
- } else {
- // Otherwise, use the class (2.6.0 feature)
- setEvictionPolicy(policy);
- }
- setEvictorShutdownTimeout(config.getEvictorShutdownTimeoutDuration());
- }
- /**
- * Sets the number of milliseconds to sleep between runs of the idle object evictor thread.
- * <ul>
- * <li>When positive, the idle object evictor thread starts.</li>
- * <li>When null or non-positive, no idle object evictor thread runs.</li>
- * </ul>
- *
- * @param timeBetweenEvictionRuns
- * duration to sleep between evictor runs
- *
- * @see #getDurationBetweenEvictionRuns()
- * @since 2.12.0
- */
- public final void setDurationBetweenEvictionRuns(final Duration timeBetweenEvictionRuns) {
- this.durationBetweenEvictionRuns = PoolImplUtils.nonNull(timeBetweenEvictionRuns, BaseObjectPoolConfig.DEFAULT_DURATION_BETWEEN_EVICTION_RUNS);
- startEvictor(this.durationBetweenEvictionRuns);
- }
- /**
- * Sets the eviction policy for this pool.
- *
- * @param evictionPolicy
- * the eviction policy for this pool.
- * @since 2.6.0
- */
- public void setEvictionPolicy(final EvictionPolicy<T> evictionPolicy) {
- this.evictionPolicy = evictionPolicy;
- }
- /**
- * Sets the eviction policy.
- *
- * @param className Eviction policy class name.
- * @param classLoader Load the class from this class loader.
- * @throws LinkageError if the linkage fails
- * @throws ExceptionInInitializerError if the initialization provoked by this method fails
- * @throws ClassNotFoundException if the class cannot be located by the specified class loader
- * @throws IllegalAccessException if this {@code Constructor} object is enforcing Java language access control and the underlying constructor is
- * inaccessible.
- * @throws IllegalArgumentException if the number of actual and formal parameters differ; if an unwrapping conversion for primitive arguments fails; or if,
- * after possible unwrapping, a parameter value cannot be converted to the corresponding formal parameter type by a method invocation conversion; if
- * this constructor pertains to an enum type.
- * @throws InstantiationException if the class that declares the underlying constructor represents an abstract class.
- * @throws InvocationTargetException if the underlying constructor throws an exception.
- * @throws ExceptionInInitializerError if the initialization provoked by this method fails.
- * @throws NoSuchMethodException if a matching method is not found.
- * @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
- * current class and invocation of {@link SecurityManager#checkPackageAccess s.checkPackageAccess()} denies access to the package of this class.
- */
- @SuppressWarnings("unchecked")
- private void setEvictionPolicy(final String className, final ClassLoader classLoader)
- throws ClassNotFoundException, InstantiationException, IllegalAccessException, InvocationTargetException, NoSuchMethodException {
- final Class<?> clazz = Class.forName(className, true, classLoader);
- final Object policy = clazz.getConstructor().newInstance();
- this.evictionPolicy = (EvictionPolicy<T>) policy;
- }
- /**
- * Sets the name of the {@link EvictionPolicy} implementation that is used by this pool. The Pool will attempt to
- * load the class using the thread context class loader. If that fails, the use the class loader for the
- * {@link EvictionPolicy} interface.
- *
- * @param evictionPolicyClassName
- * the fully qualified class name of the new eviction policy
- *
- * @see #getEvictionPolicyClassName()
- * @since 2.6.0 If loading the class using the thread context class loader fails, use the class loader for the
- * {@link EvictionPolicy} interface.
- */
- public final void setEvictionPolicyClassName(final String evictionPolicyClassName) {
- setEvictionPolicyClassName(evictionPolicyClassName, Thread.currentThread().getContextClassLoader());
- }
- /**
- * Sets the name of the {@link EvictionPolicy} implementation that is used by this pool. The Pool will attempt to
- * load the class using the given class loader. If that fails, use the class loader for the {@link EvictionPolicy}
- * interface.
- *
- * @param evictionPolicyClassName
- * the fully qualified class name of the new eviction policy
- * @param classLoader
- * the class loader to load the given {@code evictionPolicyClassName}.
- *
- * @see #getEvictionPolicyClassName()
- * @since 2.6.0 If loading the class using the given class loader fails, use the class loader for the
- * {@link EvictionPolicy} interface.
- */
- public final void setEvictionPolicyClassName(final String evictionPolicyClassName, final ClassLoader classLoader) {
- // Getting epClass here and now best matches the caller's environment
- final Class<?> epClass = EvictionPolicy.class;
- final ClassLoader epClassLoader = epClass.getClassLoader();
- try {
- try {
- setEvictionPolicy(evictionPolicyClassName, classLoader);
- } catch (final ClassCastException | ClassNotFoundException e) {
- setEvictionPolicy(evictionPolicyClassName, epClassLoader);
- }
- } catch (final ClassCastException e) {
- throw new IllegalArgumentException("Class " + evictionPolicyClassName + " from class loaders [" +
- classLoader + ", " + epClassLoader + "] do not implement " + EVICTION_POLICY_TYPE_NAME);
- } catch (final ClassNotFoundException | InstantiationException | IllegalAccessException |
- InvocationTargetException | NoSuchMethodException e) {
- throw new IllegalArgumentException(
- "Unable to create " + EVICTION_POLICY_TYPE_NAME + " instance of type " + evictionPolicyClassName,
- e);
- }
- }
- /**
- * Sets the timeout that will be used when waiting for the Evictor to shutdown if this pool is closed and it is the
- * only pool still using the value for the Evictor.
- *
- * @param evictorShutdownTimeout the timeout in milliseconds that will be used while waiting for the Evictor
- * to shut down.
- * @since 2.10.0
- */
- public final void setEvictorShutdownTimeout(final Duration evictorShutdownTimeout) {
- this.evictorShutdownTimeoutDuration = PoolImplUtils.nonNull(evictorShutdownTimeout, BaseObjectPoolConfig.DEFAULT_EVICTOR_SHUTDOWN_TIMEOUT);
- }
- /**
- * Sets the timeout that will be used when waiting for the Evictor to shutdown if this pool is closed and it is the
- * only pool still using the value for the Evictor.
- *
- * @param evictorShutdownTimeoutMillis the timeout in milliseconds that will be used while waiting for the Evictor
- * to shut down.
- * @deprecated Use {@link #setEvictorShutdownTimeout(Duration)}.
- */
- @Deprecated
- public final void setEvictorShutdownTimeoutMillis(final long evictorShutdownTimeoutMillis) {
- setEvictorShutdownTimeout(Duration.ofMillis(evictorShutdownTimeoutMillis));
- }
- /**
- * Sets whether the pool has LIFO (last in, first out) behavior with
- * respect to idle objects - always returning the most recently used object
- * from the pool, or as a FIFO (first in, first out) queue, where the pool
- * always returns the oldest object in the idle object pool.
- *
- * @param lifo {@code true} if the pool is to be configured with LIFO
- * behavior or {@code false} if the pool is to be
- * configured with FIFO behavior
- *
- * @see #getLifo()
- */
- public final void setLifo(final boolean lifo) {
- this.lifo = lifo;
- }
- /**
- * Sets the cap on the number of objects that can be allocated by the pool
- * (checked out to clients, or idle awaiting checkout) at a given time. Use
- * a negative value for no limit.
- *
- * @param maxTotal The cap on the total number of object instances managed
- * by the pool. Negative values mean that there is no limit
- * to the number of objects allocated by the pool.
- *
- * @see #getMaxTotal
- */
- public final void setMaxTotal(final int maxTotal) {
- this.maxTotal = maxTotal;
- }
- /**
- * Sets the maximum duration the
- * {@code borrowObject()} method should block before throwing an
- * exception when the pool is exhausted and
- * {@link #getBlockWhenExhausted} is true. When less than 0, the
- * {@code borrowObject()} method may block indefinitely.
- *
- * @param maxWaitDuration the maximum duration
- * {@code borrowObject()} will block or negative
- * for indefinitely.
- *
- * @see #getMaxWaitDuration
- * @see #setBlockWhenExhausted
- * @since 2.11.0
- */
- public final void setMaxWait(final Duration maxWaitDuration) {
- this.maxWaitDuration = PoolImplUtils.nonNull(maxWaitDuration, BaseObjectPoolConfig.DEFAULT_MAX_WAIT);
- }
- /**
- * Sets the maximum amount of time (in milliseconds) the
- * {@code borrowObject()} method should block before throwing an
- * exception when the pool is exhausted and
- * {@link #getBlockWhenExhausted} is true. When less than 0, the
- * {@code borrowObject()} method may block indefinitely.
- *
- * @param maxWaitMillis the maximum number of milliseconds
- * {@code borrowObject()} will block or negative
- * for indefinitely.
- *
- * @see #getMaxWaitDuration
- * @see #setBlockWhenExhausted
- * @deprecated Use {@link #setMaxWait}.
- */
- @Deprecated
- public final void setMaxWaitMillis(final long maxWaitMillis) {
- setMaxWait(Duration.ofMillis(maxWaitMillis));
- }
- /**
- * Sets whether to include statistics in exception messages.
- * <p>
- * 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
- * information.
- * </p>
- *
- * @param messagesDetails whether to include statistics in exception messages.
- * @since 2.11.0
- */
- public void setMessagesStatistics(final boolean messagesDetails) {
- this.messageStatistics = messagesDetails;
- }
- /**
- * Sets the minimum amount of time an object may sit idle in the pool
- * before it is eligible for eviction by the idle object evictor (if any -
- * see {@link #setDurationBetweenEvictionRuns(Duration)}). When non-positive,
- * no objects will be evicted from the pool due to idle time alone.
- *
- * @param minEvictableIdleTime
- * minimum amount of time an object may sit idle in the pool
- * before it is eligible for eviction
- *
- * @see #getMinEvictableIdleTime
- * @see #setTimeBetweenEvictionRuns
- * @since 2.11.0
- * @deprecated Use {@link #setMinEvictableIdleDuration(Duration)}.
- */
- @Deprecated
- public final void setMinEvictableIdle(final Duration minEvictableIdleTime) {
- this.minEvictableIdleDuration = PoolImplUtils.nonNull(minEvictableIdleTime, BaseObjectPoolConfig.DEFAULT_MIN_EVICTABLE_IDLE_DURATION);
- }
- /**
- * Sets the minimum amount of time an object may sit idle in the pool
- * before it is eligible for eviction by the idle object evictor (if any -
- * see {@link #setDurationBetweenEvictionRuns(Duration)}). When non-positive,
- * no objects will be evicted from the pool due to idle time alone.
- *
- * @param minEvictableIdleTime
- * minimum amount of time an object may sit idle in the pool
- * before it is eligible for eviction
- *
- * @see #getMinEvictableIdleTime
- * @see #setTimeBetweenEvictionRuns
- * @since 2.12.0
- */
- public final void setMinEvictableIdleDuration(final Duration minEvictableIdleTime) {
- this.minEvictableIdleDuration = PoolImplUtils.nonNull(minEvictableIdleTime, BaseObjectPoolConfig.DEFAULT_MIN_EVICTABLE_IDLE_DURATION);
- }
- /**
- * Sets the minimum amount of time an object may sit idle in the pool
- * before it is eligible for eviction by the idle object evictor (if any -
- * see {@link #setDurationBetweenEvictionRuns(Duration)}). When non-positive,
- * no objects will be evicted from the pool due to idle time alone.
- *
- * @param minEvictableIdleTime
- * minimum amount of time an object may sit idle in the pool
- * before it is eligible for eviction
- *
- * @see #getMinEvictableIdleTime
- * @see #setTimeBetweenEvictionRuns
- * @since 2.10.0
- * @deprecated Use {@link #setMinEvictableIdleDuration(Duration)}.
- */
- @Deprecated
- public final void setMinEvictableIdleTime(final Duration minEvictableIdleTime) {
- this.minEvictableIdleDuration = PoolImplUtils.nonNull(minEvictableIdleTime, BaseObjectPoolConfig.DEFAULT_MIN_EVICTABLE_IDLE_DURATION);
- }
- /**
- * Sets the minimum amount of time an object may sit idle in the pool
- * before it is eligible for eviction by the idle object evictor (if any -
- * see {@link #setTimeBetweenEvictionRunsMillis(long)}). When non-positive,
- * no objects will be evicted from the pool due to idle time alone.
- *
- * @param minEvictableIdleTimeMillis
- * minimum amount of time an object may sit idle in the pool
- * before it is eligible for eviction
- *
- * @see #getMinEvictableIdleTimeMillis
- * @see #setTimeBetweenEvictionRunsMillis
- * @deprecated Use {@link #setMinEvictableIdleTime(Duration)}.
- */
- @Deprecated
- public final void setMinEvictableIdleTimeMillis(final long minEvictableIdleTimeMillis) {
- setMinEvictableIdleTime(Duration.ofMillis(minEvictableIdleTimeMillis));
- }
- /**
- * Sets the maximum number of objects to examine during each run (if any)
- * of the idle object evictor thread. When positive, the number of tests
- * performed for a run will be the minimum of the configured value and the
- * number of idle instances in the pool. When negative, the number of tests
- * performed will be <code>ceil({@link #getNumIdle}/
- * abs({@link #getNumTestsPerEvictionRun}))</code> which means that when the
- * value is {@code -n} roughly one nth of the idle objects will be
- * tested per run.
- *
- * @param numTestsPerEvictionRun
- * max number of objects to examine during each evictor run
- *
- * @see #getNumTestsPerEvictionRun
- * @see #setTimeBetweenEvictionRunsMillis
- */
- public final void setNumTestsPerEvictionRun(final int numTestsPerEvictionRun) {
- this.numTestsPerEvictionRun = numTestsPerEvictionRun;
- }
- /**
- * Sets the minimum amount of time an object may sit idle in the pool
- * before it is eligible for eviction by the idle object evictor (if any -
- * see {@link #setDurationBetweenEvictionRuns(Duration)}),
- * with the extra condition that at least {@code minIdle} object
- * instances remain in the pool. This setting is overridden by
- * {@link #getMinEvictableIdleTime} (that is, if
- * {@link #getMinEvictableIdleTime} is positive, then
- * {@link #getSoftMinEvictableIdleTime} is ignored).
- *
- * @param softMinEvictableIdleTime
- * minimum amount of time an object may sit idle in the pool
- * before it is eligible for eviction if minIdle instances are
- * available
- *
- * @see #getSoftMinEvictableIdleTimeMillis
- * @since 2.11.0
- * @deprecated Use {@link #setSoftMinEvictableIdleDuration(Duration)}.
- */
- @Deprecated
- public final void setSoftMinEvictableIdle(final Duration softMinEvictableIdleTime) {
- this.softMinEvictableIdleDuration = PoolImplUtils.nonNull(softMinEvictableIdleTime, BaseObjectPoolConfig.DEFAULT_SOFT_MIN_EVICTABLE_IDLE_DURATION);
- }
- /**
- * Sets the minimum amount of time an object may sit idle in the pool
- * before it is eligible for eviction by the idle object evictor (if any -
- * see {@link #setDurationBetweenEvictionRuns(Duration)}),
- * with the extra condition that at least {@code minIdle} object
- * instances remain in the pool. This setting is overridden by
- * {@link #getMinEvictableIdleTime} (that is, if
- * {@link #getMinEvictableIdleTime} is positive, then
- * {@link #getSoftMinEvictableIdleTime} is ignored).
- *
- * @param softMinEvictableIdleTime
- * minimum amount of time an object may sit idle in the pool
- * before it is eligible for eviction if minIdle instances are
- * available
- *
- * @see #getSoftMinEvictableIdleTimeMillis
- * @since 2.12.0
- */
- public final void setSoftMinEvictableIdleDuration(final Duration softMinEvictableIdleTime) {
- this.softMinEvictableIdleDuration = PoolImplUtils.nonNull(softMinEvictableIdleTime, BaseObjectPoolConfig.DEFAULT_SOFT_MIN_EVICTABLE_IDLE_DURATION);
- }
- /**
- * Sets the minimum amount of time an object may sit idle in the pool
- * before it is eligible for eviction by the idle object evictor (if any -
- * see {@link #setDurationBetweenEvictionRuns(Duration)}),
- * with the extra condition that at least {@code minIdle} object
- * instances remain in the pool. This setting is overridden by
- * {@link #getMinEvictableIdleTime} (that is, if
- * {@link #getMinEvictableIdleTime} is positive, then
- * {@link #getSoftMinEvictableIdleTime} is ignored).
- *
- * @param softMinEvictableIdleTime
- * minimum amount of time an object may sit idle in the pool
- * before it is eligible for eviction if minIdle instances are
- * available
- *
- * @see #getSoftMinEvictableIdleTimeMillis
- * @since 2.10.0
- * @deprecated Use {@link #setSoftMinEvictableIdleDuration(Duration)}.
- */
- @Deprecated
- public final void setSoftMinEvictableIdleTime(final Duration softMinEvictableIdleTime) {
- this.softMinEvictableIdleDuration = PoolImplUtils.nonNull(softMinEvictableIdleTime, BaseObjectPoolConfig.DEFAULT_SOFT_MIN_EVICTABLE_IDLE_DURATION);
- }
- /**
- * Sets the minimum amount of time an object may sit idle in the pool
- * before it is eligible for eviction by the idle object evictor (if any -
- * see {@link #setTimeBetweenEvictionRunsMillis(long)}),
- * with the extra condition that at least {@code minIdle} object
- * instances remain in the pool. This setting is overridden by
- * {@link #getMinEvictableIdleTimeMillis} (that is, if
- * {@link #getMinEvictableIdleTimeMillis} is positive, then
- * {@link #getSoftMinEvictableIdleTimeMillis} is ignored).
- *
- * @param softMinEvictableIdleTimeMillis
- * minimum amount of time an object may sit idle in the pool
- * before it is eligible for eviction if minIdle instances are
- * available
- *
- * @see #getSoftMinEvictableIdleTimeMillis
- * @deprecated Use {@link #setSoftMinEvictableIdleDuration(Duration)}.
- */
- @Deprecated
- public final void setSoftMinEvictableIdleTimeMillis(final long softMinEvictableIdleTimeMillis) {
- setSoftMinEvictableIdleTime(Duration.ofMillis(softMinEvictableIdleTimeMillis));
- }
- /**
- * Sets the listener used (if any) to receive notifications of exceptions
- * unavoidably swallowed by the pool.
- *
- * @param swallowedExceptionListener The listener or {@code null}
- * for no listener
- */
- public final void setSwallowedExceptionListener(
- final SwallowedExceptionListener swallowedExceptionListener) {
- this.swallowedExceptionListener = swallowedExceptionListener;
- }
- /**
- * Sets whether objects borrowed from the pool will be validated before
- * being returned from the {@code borrowObject()} method. Validation is
- * performed by the {@code validateObject()} method of the factory
- * associated with the pool. If the object fails to validate, it will be
- * removed from the pool and destroyed, and a new attempt will be made to
- * borrow an object from the pool.
- *
- * @param testOnBorrow {@code true} if objects should be validated
- * before being returned from the
- * {@code borrowObject()} method
- *
- * @see #getTestOnBorrow
- */
- public final void setTestOnBorrow(final boolean testOnBorrow) {
- this.testOnBorrow = testOnBorrow;
- }
- /**
- * Sets whether objects created for the pool will be validated before
- * being returned from the {@code borrowObject()} method. Validation is
- * performed by the {@code validateObject()} method of the factory
- * associated with the pool. If the object fails to validate, then
- * {@code borrowObject()} will fail.
- *
- * @param testOnCreate {@code true} if newly created objects should be
- * validated before being returned from the
- * {@code borrowObject()} method
- *
- * @see #getTestOnCreate
- * @since 2.2
- */
- public final void setTestOnCreate(final boolean testOnCreate) {
- this.testOnCreate = testOnCreate;
- }
- /**
- * Sets whether objects borrowed from the pool will be validated when
- * they are returned to the pool via the {@code returnObject()} method.
- * Validation is performed by the {@code validateObject()} method of
- * the factory associated with the pool. Returning objects that fail validation
- * are destroyed rather then being returned the pool.
- *
- * @param testOnReturn {@code true} if objects are validated on
- * return to the pool via the
- * {@code returnObject()} method
- *
- * @see #getTestOnReturn
- */
- public final void setTestOnReturn(final boolean testOnReturn) {
- this.testOnReturn = testOnReturn;
- }
- /**
- * Sets whether objects sitting idle in the pool will be validated by the
- * idle object evictor (if any - see
- * {@link #setDurationBetweenEvictionRuns(Duration)}). Validation is performed
- * by the {@code validateObject()} method of the factory associated
- * with the pool. If the object fails to validate, it will be removed from
- * the pool and destroyed. Note that setting this property has no effect
- * unless the idle object evictor is enabled by setting
- * {@code timeBetweenEvictionRunsMillis} to a positive value.
- *
- * @param testWhileIdle
- * {@code true} so objects will be validated by the evictor
- *
- * @see #getTestWhileIdle
- * @see #setTimeBetweenEvictionRuns
- */
- public final void setTestWhileIdle(final boolean testWhileIdle) {
- this.testWhileIdle = testWhileIdle;
- }
- /**
- * Sets the number of milliseconds to sleep between runs of the idle object evictor thread.
- * <ul>
- * <li>When positive, the idle object evictor thread starts.</li>
- * <li>When non-positive, no idle object evictor thread runs.</li>
- * </ul>
- *
- * @param timeBetweenEvictionRuns
- * duration to sleep between evictor runs
- *
- * @see #getDurationBetweenEvictionRuns()
- * @since 2.10.0
- * @deprecated Use {@link #setDurationBetweenEvictionRuns(Duration)}.
- */
- @Deprecated
- public final void setTimeBetweenEvictionRuns(final Duration timeBetweenEvictionRuns) {
- this.durationBetweenEvictionRuns = PoolImplUtils.nonNull(timeBetweenEvictionRuns, BaseObjectPoolConfig.DEFAULT_DURATION_BETWEEN_EVICTION_RUNS);
- startEvictor(this.durationBetweenEvictionRuns);
- }
- /**
- * Sets the number of milliseconds to sleep between runs of the idle object evictor thread.
- * <ul>
- * <li>When positive, the idle object evictor thread starts.</li>
- * <li>When non-positive, no idle object evictor thread runs.</li>
- * </ul>
- *
- * @param timeBetweenEvictionRunsMillis
- * number of milliseconds to sleep between evictor runs
- *
- * @see #getDurationBetweenEvictionRuns()
- * @deprecated Use {@link #setDurationBetweenEvictionRuns(Duration)}.
- */
- @Deprecated
- public final void setTimeBetweenEvictionRunsMillis(final long timeBetweenEvictionRunsMillis) {
- setTimeBetweenEvictionRuns(Duration.ofMillis(timeBetweenEvictionRunsMillis));
- }
- /**
- * <p>Starts the evictor with the given delay. If there is an evictor
- * running when this method is called, it is stopped and replaced with a
- * new evictor with the specified delay.</p>
- *
- * <p>This method needs to be final, since it is called from a constructor.
- * See POOL-195.</p>
- *
- * @param delay time in milliseconds before start and between eviction runs
- */
- final void startEvictor(final Duration delay) {
- synchronized (evictionLock) {
- final boolean isPositiverDelay = PoolImplUtils.isPositive(delay);
- if (evictor == null) { // Starting evictor for the first time or after a cancel
- if (isPositiverDelay) { // Starting new evictor
- evictor = new Evictor();
- EvictionTimer.schedule(evictor, delay, delay);
- }
- } else if (isPositiverDelay) { // Stop or restart of existing evictor: Restart
- synchronized (EvictionTimer.class) { // Ensure no cancel can happen between cancel / schedule calls
- EvictionTimer.cancel(evictor, evictorShutdownTimeoutDuration, true);
- evictor = null;
- evictionIterator = null;
- evictor = new Evictor();
- EvictionTimer.schedule(evictor, delay, delay);
- }
- } else { // Stopping evictor
- EvictionTimer.cancel(evictor, evictorShutdownTimeoutDuration, false);
- }
- }
- }
- /**
- * Stops the evictor.
- */
- void stopEvictor() {
- startEvictor(Duration.ofMillis(-1L));
- }
- /**
- * Swallows an exception and notifies the configured listener for swallowed
- * exceptions queue.
- *
- * @param swallowException exception to be swallowed
- */
- final void swallowException(final Exception swallowException) {
- final SwallowedExceptionListener listener = getSwallowedExceptionListener();
- if (listener == null) {
- return;
- }
- try {
- listener.onSwallowException(swallowException);
- } catch (final VirtualMachineError e) {
- throw e;
- } catch (final Throwable ignored) {
- // Ignore. Enjoy the irony.
- }
- }
- @Override
- protected void toStringAppendFields(final StringBuilder builder) {
- builder.append("maxTotal=");
- builder.append(maxTotal);
- builder.append(", blockWhenExhausted=");
- builder.append(blockWhenExhausted);
- builder.append(", maxWaitDuration=");
- builder.append(maxWaitDuration);
- builder.append(", lifo=");
- builder.append(lifo);
- builder.append(", fairness=");
- builder.append(fairness);
- builder.append(", testOnCreate=");
- builder.append(testOnCreate);
- builder.append(", testOnBorrow=");
- builder.append(testOnBorrow);
- builder.append(", testOnReturn=");
- builder.append(testOnReturn);
- builder.append(", testWhileIdle=");
- builder.append(testWhileIdle);
- builder.append(", durationBetweenEvictionRuns=");
- builder.append(durationBetweenEvictionRuns);
- builder.append(", numTestsPerEvictionRun=");
- builder.append(numTestsPerEvictionRun);
- builder.append(", minEvictableIdleTimeDuration=");
- builder.append(minEvictableIdleDuration);
- builder.append(", softMinEvictableIdleTimeDuration=");
- builder.append(softMinEvictableIdleDuration);
- builder.append(", evictionPolicy=");
- builder.append(evictionPolicy);
- builder.append(", closeLock=");
- builder.append(closeLock);
- builder.append(", closed=");
- builder.append(closed);
- builder.append(", evictionLock=");
- builder.append(evictionLock);
- builder.append(", evictor=");
- builder.append(evictor);
- builder.append(", evictionIterator=");
- builder.append(evictionIterator);
- builder.append(", factoryClassLoader=");
- builder.append(factoryClassLoader);
- builder.append(", oname=");
- builder.append(objectName);
- builder.append(", creationStackTrace=");
- builder.append(creationStackTrace);
- builder.append(", borrowedCount=");
- builder.append(borrowedCount);
- builder.append(", returnedCount=");
- builder.append(returnedCount);
- builder.append(", createdCount=");
- builder.append(createdCount);
- builder.append(", destroyedCount=");
- builder.append(destroyedCount);
- builder.append(", destroyedByEvictorCount=");
- builder.append(destroyedByEvictorCount);
- builder.append(", destroyedByBorrowValidationCount=");
- builder.append(destroyedByBorrowValidationCount);
- builder.append(", activeTimes=");
- builder.append(activeTimes);
- builder.append(", idleTimes=");
- builder.append(idleTimes);
- builder.append(", waitTimes=");
- builder.append(waitTimes);
- builder.append(", maxBorrowWaitDuration=");
- builder.append(maxBorrowWaitDuration);
- builder.append(", swallowedExceptionListener=");
- builder.append(swallowedExceptionListener);
- }
- /**
- * Updates statistics after an object is borrowed from the pool.
- *
- * @param p object borrowed from the pool
- * @param waitDuration that the borrowing thread had to wait
- */
- final void updateStatsBorrow(final PooledObject<T> p, final Duration waitDuration) {
- borrowedCount.incrementAndGet();
- idleTimes.add(p.getIdleDuration());
- waitTimes.add(waitDuration);
- // lock-free optimistic-locking maximum
- Duration currentMaxDuration;
- do {
- currentMaxDuration = maxBorrowWaitDuration.get();
- if (currentMaxDuration.compareTo(waitDuration) >= 0) {
- break;
- }
- } while (!maxBorrowWaitDuration.compareAndSet(currentMaxDuration, waitDuration));
- }
- /**
- * Updates statistics after an object is returned to the pool.
- *
- * @param activeTime the amount of time (in milliseconds) that the returning
- * object was checked out
- */
- final void updateStatsReturn(final Duration activeTime) {
- returnedCount.incrementAndGet();
- activeTimes.add(activeTime);
- }
- }