/*
* 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.util.Arrays;
import java.util.Deque;
import java.util.Iterator;
import java.util.TimerTask;
import java.util.concurrent.ScheduledFuture;
import java.util.concurrent.TimeUnit;
import java.util.concurrent.atomic.AtomicLong;
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 GenericObjectPool
and GenericKeyedObjectPool
. The primary reason this class exists is reduce code duplication between the two pool implementations. Type parameters: - <T> – Type of element pooled in this pool.
This class is intended to be thread-safe.
Since: 2.0
/**
* 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.
*
* @param <T> Type of element pooled in this pool.
*
* This class is intended to be thread-safe.
*
* @since 2.0
*/
public abstract class BaseGenericObjectPool<T> extends BaseObject {
// Constants
The size of the caches used to store historical data for some attributes
so that rolling means may be calculated.
/**
* 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();
// Configuration attributes
private volatile int maxTotal =
GenericKeyedObjectPoolConfig.DEFAULT_MAX_TOTAL;
private volatile boolean blockWhenExhausted =
BaseObjectPoolConfig.DEFAULT_BLOCK_WHEN_EXHAUSTED;
private volatile long maxWaitMillis =
BaseObjectPoolConfig.DEFAULT_MAX_WAIT_MILLIS;
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 long timeBetweenEvictionRunsMillis =
BaseObjectPoolConfig.DEFAULT_TIME_BETWEEN_EVICTION_RUNS_MILLIS;
private volatile int numTestsPerEvictionRun =
BaseObjectPoolConfig.DEFAULT_NUM_TESTS_PER_EVICTION_RUN;
private volatile long minEvictableIdleTimeMillis =
BaseObjectPoolConfig.DEFAULT_MIN_EVICTABLE_IDLE_TIME_MILLIS;
private volatile long softMinEvictableIdleTimeMillis =
BaseObjectPoolConfig.DEFAULT_SOFT_MIN_EVICTABLE_IDLE_TIME_MILLIS;
private volatile EvictionPolicy<T> evictionPolicy;
private volatile long evictorShutdownTimeoutMillis =
BaseObjectPoolConfig.DEFAULT_EVICTOR_SHUTDOWN_TIMEOUT_MILLIS;
// Internal (primarily state) attributes
final Object closeLock = new Object();
volatile boolean closed = false;
final Object evictionLock = new Object();
private Evictor evictor = null; // @GuardedBy("evictionLock")
EvictionIterator evictionIterator = null; // @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(0);
private final AtomicLong returnedCount = new AtomicLong(0);
final AtomicLong createdCount = new AtomicLong(0);
final AtomicLong destroyedCount = new AtomicLong(0);
final AtomicLong destroyedByEvictorCount = new AtomicLong(0);
final AtomicLong destroyedByBorrowValidationCount = new AtomicLong(0);
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 AtomicLong maxBorrowWaitTimeMillis = new AtomicLong(0L);
private volatile SwallowedExceptionListener swallowedExceptionListener = null;
Handles JMX registration (if required) and the initialization required for
monitoring.
Params: - config – Pool configuration
- jmxNameBase – The default base JMX name for the new pool unless
overridden by the config
- jmxNamePrefix – Prefix to be used for JMX name for the new pool
/**
* 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();
}
Returns 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.
See Also: Returns: the cap on the total number of object instances managed by the
pool.
/**
* Returns 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;
}
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.
Params: - 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 Also:
/**
* 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;
}
Returns whether to block when the borrowObject()
method is
invoked when the pool is exhausted (the maximum number of "active"
objects has been reached).
See Also: Returns: true
if borrowObject()
should block
when the pool is exhausted
/**
* Returns whether to block when the <code>borrowObject()</code> method is
* invoked when the pool is exhausted (the maximum number of "active"
* objects has been reached).
*
* @return <code>true</code> if <code>borrowObject()</code> should block
* when the pool is exhausted
*
* @see #setBlockWhenExhausted
*/
public final boolean getBlockWhenExhausted() {
return blockWhenExhausted;
}
Sets whether to block when the borrowObject()
method is
invoked when the pool is exhausted (the maximum number of "active"
objects has been reached).
Params: - blockWhenExhausted –
true
if
borrowObject()
should block
when the pool is exhausted
See Also:
/**
* Sets whether to block when the <code>borrowObject()</code> method is
* invoked when the pool is exhausted (the maximum number of "active"
* objects has been reached).
*
* @param blockWhenExhausted <code>true</code> if
* <code>borrowObject()</code> should block
* when the pool is exhausted
*
* @see #getBlockWhenExhausted
*/
public final void setBlockWhenExhausted(final boolean blockWhenExhausted) {
this.blockWhenExhausted = blockWhenExhausted;
}
protected void setConfig(final BaseObjectPoolConfig<T> conf) {
setLifo(conf.getLifo());
setMaxWaitMillis(conf.getMaxWaitMillis());
setBlockWhenExhausted(conf.getBlockWhenExhausted());
setTestOnCreate(conf.getTestOnCreate());
setTestOnBorrow(conf.getTestOnBorrow());
setTestOnReturn(conf.getTestOnReturn());
setTestWhileIdle(conf.getTestWhileIdle());
setNumTestsPerEvictionRun(conf.getNumTestsPerEvictionRun());
setMinEvictableIdleTimeMillis(conf.getMinEvictableIdleTimeMillis());
setTimeBetweenEvictionRunsMillis(conf.getTimeBetweenEvictionRunsMillis());
setSoftMinEvictableIdleTimeMillis(conf.getSoftMinEvictableIdleTimeMillis());
final EvictionPolicy<T> policy = conf.getEvictionPolicy();
if (policy == null) {
// Use the class name (pre-2.6.0 compatible)
setEvictionPolicyClassName(conf.getEvictionPolicyClassName());
} else {
// Otherwise, use the class (2.6.0 feature)
setEvictionPolicy(policy);
}
setEvictorShutdownTimeoutMillis(conf.getEvictorShutdownTimeoutMillis());
}
Returns the maximum amount of time (in milliseconds) the
borrowObject()
method should block before throwing an exception when the pool is exhausted and getBlockWhenExhausted
is true. When less than 0, the borrowObject()
method may block indefinitely.
See Also: Returns: the maximum number of milliseconds borrowObject()
will block.
/**
* Returns the maximum amount of time (in milliseconds) the
* <code>borrowObject()</code> method should block before throwing an
* exception when the pool is exhausted and
* {@link #getBlockWhenExhausted} is true. When less than 0, the
* <code>borrowObject()</code> method may block indefinitely.
*
* @return the maximum number of milliseconds <code>borrowObject()</code>
* will block.
*
* @see #setMaxWaitMillis
* @see #setBlockWhenExhausted
*/
public final long getMaxWaitMillis() {
return maxWaitMillis;
}
Sets the maximum amount of time (in milliseconds) the
borrowObject()
method should block before throwing an exception when the pool is exhausted and getBlockWhenExhausted
is true. When less than 0, the borrowObject()
method may block indefinitely.
Params: - maxWaitMillis – the maximum number of milliseconds
borrowObject()
will block or negative
for indefinitely.
See Also:
/**
* Sets the maximum amount of time (in milliseconds) the
* <code>borrowObject()</code> method should block before throwing an
* exception when the pool is exhausted and
* {@link #getBlockWhenExhausted} is true. When less than 0, the
* <code>borrowObject()</code> method may block indefinitely.
*
* @param maxWaitMillis the maximum number of milliseconds
* <code>borrowObject()</code> will block or negative
* for indefinitely.
*
* @see #getMaxWaitMillis
* @see #setBlockWhenExhausted
*/
public final void setMaxWaitMillis(final long maxWaitMillis) {
this.maxWaitMillis = maxWaitMillis;
}
Returns whether the pool has LIFO (last in, first out) behaviour 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.
See Also: Returns: true
if the pool is configured with LIFO behaviour
or false
if the pool is configured with FIFO
behaviour
/**
* Returns whether the pool has LIFO (last in, first out) behaviour 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</code> if the pool is configured with LIFO behaviour
* or <code>false</code> if the pool is configured with FIFO
* behaviour
*
* @see #setLifo
*/
public final boolean getLifo() {
return lifo;
}
Returns 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.
Returns: true
if waiting threads are to be served
by the pool in arrival order
/**
* Returns 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</code> if waiting threads are to be served
* by the pool in arrival order
*/
public final boolean getFairness() {
return fairness;
}
Sets whether the pool has LIFO (last in, first out) behaviour 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.
Params: - lifo –
true
if the pool is to be configured with LIFO
behaviour or false
if the pool is to be
configured with FIFO behaviour
See Also:
/**
* Sets whether the pool has LIFO (last in, first out) behaviour 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</code> if the pool is to be configured with LIFO
* behaviour or <code>false</code> if the pool is to be
* configured with FIFO behaviour
*
* @see #getLifo()
*/
public final void setLifo(final boolean lifo) {
this.lifo = lifo;
}
Returns whether objects created for the pool will be validated before
being returned from the borrowObject()
method. Validation is
performed by the validateObject()
method of the factory
associated with the pool. If the object fails to validate, then
borrowObject()
will fail.
See Also: Returns: true
if newly created objects are validated before
being returned from the borrowObject()
methodSince: 2.2
/**
* Returns whether objects created for the pool will be validated before
* being returned from the <code>borrowObject()</code> method. Validation is
* performed by the <code>validateObject()</code> method of the factory
* associated with the pool. If the object fails to validate, then
* <code>borrowObject()</code> will fail.
*
* @return <code>true</code> if newly created objects are validated before
* being returned from the <code>borrowObject()</code> method
*
* @see #setTestOnCreate
*
* @since 2.2
*/
public final boolean getTestOnCreate() {
return testOnCreate;
}
Sets whether objects created for the pool will be validated before
being returned from the borrowObject()
method. Validation is
performed by the validateObject()
method of the factory
associated with the pool. If the object fails to validate, then
borrowObject()
will fail.
Params: - testOnCreate –
true
if newly created objects should be
validated before being returned from the
borrowObject()
method
See Also: Since: 2.2
/**
* Sets whether objects created for the pool will be validated before
* being returned from the <code>borrowObject()</code> method. Validation is
* performed by the <code>validateObject()</code> method of the factory
* associated with the pool. If the object fails to validate, then
* <code>borrowObject()</code> will fail.
*
* @param testOnCreate <code>true</code> if newly created objects should be
* validated before being returned from the
* <code>borrowObject()</code> method
*
* @see #getTestOnCreate
*
* @since 2.2
*/
public final void setTestOnCreate(final boolean testOnCreate) {
this.testOnCreate = testOnCreate;
}
Returns whether objects borrowed from the pool will be validated before
being returned from the borrowObject()
method. Validation is
performed by the 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.
See Also: Returns: true
if objects are validated before being returned
from the borrowObject()
method
/**
* Returns whether objects borrowed from the pool will be validated before
* being returned from the <code>borrowObject()</code> method. Validation is
* performed by the <code>validateObject()</code> 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</code> if objects are validated before being returned
* from the <code>borrowObject()</code> method
*
* @see #setTestOnBorrow
*/
public final boolean getTestOnBorrow() {
return testOnBorrow;
}
Sets whether objects borrowed from the pool will be validated before
being returned from the borrowObject()
method. Validation is
performed by the 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.
Params: - testOnBorrow –
true
if objects should be validated
before being returned from the
borrowObject()
method
See Also:
/**
* Sets whether objects borrowed from the pool will be validated before
* being returned from the <code>borrowObject()</code> method. Validation is
* performed by the <code>validateObject()</code> 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</code> if objects should be validated
* before being returned from the
* <code>borrowObject()</code> method
*
* @see #getTestOnBorrow
*/
public final void setTestOnBorrow(final boolean testOnBorrow) {
this.testOnBorrow = testOnBorrow;
}
Returns whether objects borrowed from the pool will be validated when
they are returned to the pool via the returnObject()
method.
Validation is performed by the validateObject()
method of
the factory associated with the pool. Returning objects that fail validation
are destroyed rather then being returned the pool.
See Also: Returns: true
if objects are validated on return to
the pool via the returnObject()
method
/**
* Returns whether objects borrowed from the pool will be validated when
* they are returned to the pool via the <code>returnObject()</code> method.
* Validation is performed by the <code>validateObject()</code> method of
* the factory associated with the pool. Returning objects that fail validation
* are destroyed rather then being returned the pool.
*
* @return <code>true</code> if objects are validated on return to
* the pool via the <code>returnObject()</code> method
*
* @see #setTestOnReturn
*/
public final boolean getTestOnReturn() {
return testOnReturn;
}
Sets whether objects borrowed from the pool will be validated when
they are returned to the pool via the returnObject()
method.
Validation is performed by the validateObject()
method of
the factory associated with the pool. Returning objects that fail validation
are destroyed rather then being returned the pool.
Params: - testOnReturn –
true
if objects are validated on
return to the pool via the
returnObject()
method
See Also:
/**
* Sets whether objects borrowed from the pool will be validated when
* they are returned to the pool via the <code>returnObject()</code> method.
* Validation is performed by the <code>validateObject()</code> 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</code> if objects are validated on
* return to the pool via the
* <code>returnObject()</code> method
*
* @see #getTestOnReturn
*/
public final void setTestOnReturn(final boolean testOnReturn) {
this.testOnReturn = testOnReturn;
}
Returns whether objects sitting idle in the pool will be validated by the idle object evictor (if any - see setTimeBetweenEvictionRunsMillis(long)
). Validation is performed by the validateObject()
method of the factory associated
with the pool. If the object fails to validate, it will be removed from
the pool and destroyed.
See Also: Returns: true
if objects will be validated by the evictor
/**
* Returns whether objects sitting idle in the pool will be validated by the
* idle object evictor (if any - see
* {@link #setTimeBetweenEvictionRunsMillis(long)}). Validation is performed
* by the <code>validateObject()</code> 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</code> if objects will be validated by the evictor
*
* @see #setTestWhileIdle
* @see #setTimeBetweenEvictionRunsMillis
*/
public final boolean getTestWhileIdle() {
return testWhileIdle;
}
Returns whether objects sitting idle in the pool will be validated by the idle object evictor (if any - see setTimeBetweenEvictionRunsMillis(long)
). Validation is performed by the 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
timeBetweenEvictionRunsMillis
to a positive value.
Params: - testWhileIdle –
true
so objects will be validated by the evictor
See Also:
/**
* Returns whether objects sitting idle in the pool will be validated by the
* idle object evictor (if any - see
* {@link #setTimeBetweenEvictionRunsMillis(long)}). Validation is performed
* by the <code>validateObject()</code> 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</code> to a positive value.
*
* @param testWhileIdle
* <code>true</code> so objects will be validated by the evictor
*
* @see #getTestWhileIdle
* @see #setTimeBetweenEvictionRunsMillis
*/
public final void setTestWhileIdle(final boolean testWhileIdle) {
this.testWhileIdle = testWhileIdle;
}
Returns 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.
See Also: Returns: number of milliseconds to sleep between evictor runs
/**
* Returns 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
*/
public final long getTimeBetweenEvictionRunsMillis() {
return timeBetweenEvictionRunsMillis;
}
Sets the number of milliseconds to sleep between runs of the idle object evictor thread.
- When positive, the idle object evictor thread starts.
- When non-positive, no idle object evictor thread runs.
Params: - timeBetweenEvictionRunsMillis –
number of milliseconds to sleep between evictor runs
See Also:
/**
* 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 #getTimeBetweenEvictionRunsMillis
*/
public final void setTimeBetweenEvictionRunsMillis(
final long timeBetweenEvictionRunsMillis) {
this.timeBetweenEvictionRunsMillis = timeBetweenEvictionRunsMillis;
startEvictor(timeBetweenEvictionRunsMillis);
}
Returns 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 ceil(getNumIdle
/ abs(getNumTestsPerEvictionRun
))
which means that when the
value is -n
roughly one nth of the idle objects will be
tested per run.
See Also: Returns: max number of objects to examine during each evictor run
/**
* Returns 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</code> 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;
}
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 ceil(getNumIdle
/ abs(getNumTestsPerEvictionRun
))
which means that when the
value is -n
roughly one nth of the idle objects will be
tested per run.
Params: - numTestsPerEvictionRun –
max number of objects to examine during each evictor run
See Also:
/**
* 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</code> 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;
}
Returns 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 setTimeBetweenEvictionRunsMillis(long)
). When non-positive, no objects will be evicted from the pool due to idle time alone. See Also: Returns: minimum amount of time an object may sit idle in the pool before
it is eligible for eviction
/**
* Returns 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
*/
public final long getMinEvictableIdleTimeMillis() {
return minEvictableIdleTimeMillis;
}
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 setTimeBetweenEvictionRunsMillis(long)
). When non-positive, no objects will be evicted from the pool due to idle time alone. Params: - minEvictableIdleTimeMillis –
minimum amount of time an object may sit idle in the pool
before it is eligible for eviction
See Also:
/**
* 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
*/
public final void setMinEvictableIdleTimeMillis(
final long minEvictableIdleTimeMillis) {
this.minEvictableIdleTimeMillis = minEvictableIdleTimeMillis;
}
Returns 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 setTimeBetweenEvictionRunsMillis(long)
), with the extra condition that at least minIdle
object instances remain in the pool. This setting is overridden by getMinEvictableIdleTimeMillis
(that is, if getMinEvictableIdleTimeMillis
is positive, then getSoftMinEvictableIdleTimeMillis
is ignored). See Also: Returns: minimum amount of time an object may sit idle in the pool before
it is eligible for eviction if minIdle instances are available
/**
* Returns 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</code> 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
*/
public final long getSoftMinEvictableIdleTimeMillis() {
return softMinEvictableIdleTimeMillis;
}
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 setTimeBetweenEvictionRunsMillis(long)
), with the extra condition that at least minIdle
object instances remain in the pool. This setting is overridden by getMinEvictableIdleTimeMillis
(that is, if getMinEvictableIdleTimeMillis
is positive, then getSoftMinEvictableIdleTimeMillis
is ignored). Params: - 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 Also:
/**
* 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</code> 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
*/
public final void setSoftMinEvictableIdleTimeMillis(
final long softMinEvictableIdleTimeMillis) {
this.softMinEvictableIdleTimeMillis = softMinEvictableIdleTimeMillis;
}
Returns the name of the EvictionPolicy
implementation that is used by this pool. See Also: Returns: The fully qualified class name of the EvictionPolicy
/**
* Returns 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();
}
Sets the eviction policy for this pool.
Params: - evictionPolicy –
the eviction policy for this pool.
Since: 2.6.0
/**
* 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 name of the 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 EvictionPolicy
interface. Params: - evictionPolicyClassName –
the fully qualified class name of the new eviction policy
- classLoader – the class loader to load the given
evictionPolicyClassName
.
See Also: Since: 2.6.0 If loading the class using the given class loader fails, use the class loader for the EvictionPolicy
interface.
/**
* 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) {
final String exMessage = "Unable to create " + EVICTION_POLICY_TYPE_NAME + " instance of type "
+ evictionPolicyClassName;
throw new IllegalArgumentException(exMessage, e);
}
}
@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 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 EvictionPolicy
interface. Params: - evictionPolicyClassName –
the fully qualified class name of the new eviction policy
See Also: Since: 2.6.0 If loading the class using the thread context class loader fails, use the class loader for the EvictionPolicy
interface.
/**
* 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());
}
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.
Returns: The timeout in milliseconds that will be used while waiting for
the Evictor to shut down.
/**
* 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.
*/
public final long getEvictorShutdownTimeoutMillis() {
return evictorShutdownTimeoutMillis;
}
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
the value for the Evictor.
Params: - evictorShutdownTimeoutMillis – the timeout in milliseconds that
will be used while waiting for the
Evictor to shut down.
/**
* 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
* the value for the Evictor.
*
* @param evictorShutdownTimeoutMillis the timeout in milliseconds that
* will be used while waiting for the
* Evictor to shut down.
*/
public final void setEvictorShutdownTimeoutMillis(
final long evictorShutdownTimeoutMillis) {
this.evictorShutdownTimeoutMillis = evictorShutdownTimeoutMillis;
}
Closes the pool, destroys the remaining idle objects and, if registered
in JMX, deregisters it.
/**
* Closes the pool, destroys the remaining idle objects and, if registered
* in JMX, deregisters it.
*/
public abstract void close();
Has this pool instance been closed.
Returns: true
when this pool has been closed.
/**
* Has this pool instance been closed.
* @return <code>true</code> when this pool has been closed.
*/
public final boolean isClosed() {
return closed;
}
Perform numTests
idle object eviction tests, evicting
examined objects that meet the criteria for eviction. If
testWhileIdle
is true, examined objects are validated
when visited (and removed if invalid); otherwise only objects that
have been idle for more than minEvicableIdleTimeMillis
are removed.
Throws: - Exception – when there is a problem evicting idle objects.
/**
* <p>Perform <code>numTests</code> idle object eviction tests, evicting
* examined objects that meet the criteria for eviction. If
* <code>testWhileIdle</code> is true, examined objects are validated
* when visited (and removed if invalid); otherwise only objects that
* have been idle for more than <code>minEvicableIdleTimeMillis</code>
* are removed.</p>
*
* @throws Exception when there is a problem evicting idle objects.
*/
public abstract void evict() throws Exception;
Returns the EvictionPolicy
defined for this pool. Returns: the eviction policy Since: 2.4 Since: 2.6.0 Changed access from protected to public.
/**
* Returns 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;
}
Verifies that the pool is open.
Throws: - IllegalStateException – if the pool is closed.
/**
* 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");
}
}
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.
This method needs to be final, since it is called from a constructor.
See POOL-195.
Params: - delay – time in milliseconds before start and between eviction runs
/**
* <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 long delay) {
synchronized (evictionLock) {
EvictionTimer.cancel(evictor, evictorShutdownTimeoutMillis, TimeUnit.MILLISECONDS);
evictor = null;
evictionIterator = null;
if (delay > 0) {
evictor = new Evictor();
EvictionTimer.schedule(evictor, delay, delay);
}
}
}
Stops the evictor.
/**
* Stops the evictor.
*/
void stopEvictor() {
startEvictor(-1L);
}
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
/**
* 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;
// Monitoring (primarily JMX) related methods
Provides the name under which the pool has been registered with the
platform MBean server or null
if the pool has not been
registered.
Returns: the JMX name
/**
* Provides the name under which the pool has been registered with the
* platform MBean server or <code>null</code> if the pool has not been
* registered.
* @return the JMX name
*/
public final ObjectName getJmxName() {
return objectName;
}
Provides 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 close()
method. This method is provided to assist with identifying code that creates but does not close it thereby creating a memory leak. Returns: pool creation stack trace
/**
* Provides 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;
}
The total number of objects successfully borrowed from this pool over the
lifetime of the pool.
Returns: the borrowed object count
/**
* 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();
}
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.
Returns: the returned object count
/**
* 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();
}
The total number of objects created for this pool over the lifetime of
the pool.
Returns: the created object count
/**
* 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();
}
The total number of objects destroyed by this pool over the lifetime of
the pool.
Returns: the destroyed object count
/**
* 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();
}
The total number of objects destroyed by the evictor associated with this
pool over the lifetime of the pool.
Returns: the evictor destroyed object count
/**
* 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();
}
The total number of objects destroyed by this pool as a result of failing
validation during borrowObject()
over the lifetime of the
pool.
Returns: validation destroyed object count
/**
* The total number of objects destroyed by this pool as a result of failing
* validation during <code>borrowObject()</code> over the lifetime of the
* pool.
* @return validation destroyed object count
*/
public final long getDestroyedByBorrowValidationCount() {
return destroyedByBorrowValidationCount.get();
}
The mean time objects are active for based on the last BaseGenericObjectPool<T>.MEAN_TIMING_STATS_CACHE_SIZE
objects returned to the pool. Returns: mean time an object has been checked out from the pool among
recently returned objects
/**
* 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
*/
public final long getMeanActiveTimeMillis() {
return activeTimes.getMean();
}
The mean time objects are idle for based on the last BaseGenericObjectPool<T>.MEAN_TIMING_STATS_CACHE_SIZE
objects borrowed from the pool. Returns: mean time an object has been idle in the pool among recently
borrowed objects
/**
* 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
*/
public final long getMeanIdleTimeMillis() {
return idleTimes.getMean();
}
The mean time threads wait to borrow an object based on the last BaseGenericObjectPool<T>.MEAN_TIMING_STATS_CACHE_SIZE
objects borrowed from the pool. Returns: mean time in milliseconds that a recently served thread has had
to wait to borrow an object from the pool
/**
* 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
*/
public final long getMeanBorrowWaitTimeMillis() {
return waitTimes.getMean();
}
The maximum time a thread has waited to borrow objects from the pool.
Returns: maximum wait time in milliseconds since the pool was created
/**
* The maximum time a thread has waited to borrow objects from the pool.
* @return maximum wait time in milliseconds since the pool was created
*/
public final long getMaxBorrowWaitTimeMillis() {
return maxBorrowWaitTimeMillis.get();
}
The number of instances currently idle in this pool.
Returns: count of instances available for checkout from the pool
/**
* The number of instances currently idle in this pool.
* @return count of instances available for checkout from the pool
*/
public abstract int getNumIdle();
The listener used (if any) to receive notifications of exceptions
unavoidably swallowed by the pool.
Returns: The listener or null
for no listener
/**
* The listener used (if any) to receive notifications of exceptions
* unavoidably swallowed by the pool.
*
* @return The listener or <code>null</code> for no listener
*/
public final SwallowedExceptionListener getSwallowedExceptionListener() {
return swallowedExceptionListener;
}
The listener used (if any) to receive notifications of exceptions
unavoidably swallowed by the pool.
Params: - swallowedExceptionListener – The listener or
null
for no listener
/**
* The listener used (if any) to receive notifications of exceptions
* unavoidably swallowed by the pool.
*
* @param swallowedExceptionListener The listener or <code>null</code>
* for no listener
*/
public final void setSwallowedExceptionListener(
final SwallowedExceptionListener swallowedExceptionListener) {
this.swallowedExceptionListener = swallowedExceptionListener;
}
Swallows an exception and notifies the configured listener for swallowed
exceptions queue.
Params: - swallowException – exception to be swallowed
/**
* 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 t) {
// Ignore. Enjoy the irony.
}
}
Updates statistics after an object is borrowed from the pool.
Params: - p – object borrowed from the pool
- waitTime – time (in milliseconds) that the borrowing thread had to wait
/**
* Updates statistics after an object is borrowed from the pool.
* @param p object borrowed from the pool
* @param waitTime time (in milliseconds) that the borrowing thread had to wait
*/
final void updateStatsBorrow(final PooledObject<T> p, final long waitTime) {
borrowedCount.incrementAndGet();
idleTimes.add(p.getIdleTimeMillis());
waitTimes.add(waitTime);
// lock-free optimistic-locking maximum
long currentMax;
do {
currentMax = maxBorrowWaitTimeMillis.get();
if (currentMax >= waitTime) {
break;
}
} while (!maxBorrowWaitTimeMillis.compareAndSet(currentMax, waitTime));
}
Updates statistics after an object is returned to the pool.
Params: - activeTime – the amount of time (in milliseconds) that the returning
object was checked out
/**
* 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 long activeTime) {
returnedCount.incrementAndGet();
activeTimes.add(activeTime);
}
Marks the object as returning to the pool.
Params: - pooledObject – instance to return to the keyed pool
/**
* 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) {
final PooledObjectState state = pooledObject.getState();
if (state != PooledObjectState.ALLOCATED) {
throw new IllegalStateException(
"Object has already been returned to this pool or is invalid");
}
pooledObject.markReturning(); // Keep from being marked abandoned
}
}
Unregisters this pool's MBean.
/**
* Unregisters this pool's MBean.
*/
final void jmxUnregister() {
if (objectName != null) {
try {
ManagementFactory.getPlatformMBeanServer().unregisterMBean(
objectName);
} catch (final MBeanRegistrationException | InstanceNotFoundException e) {
swallowException(e);
}
}
}
Registers the pool with the platform MBean server.
The registered name will be
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.
Params: - config – Pool configuration
- jmxNameBase – default base JMX name for this pool
- jmxNamePrefix – name prefix
Returns: registered ObjectName, null if registration fails
/**
* Registers the pool with the platform MBean server.
* The registered name will be
* <code>jmxNameBase + jmxNamePrefix + i</code> 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);
}
mbs.registerMBean(this, objName);
newObjectName = objName;
registered = true;
} 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;
}
Gets the stack trace of an exception as a string.
Params: - e – exception to trace
Returns: exception stack trace as a string
/**
* 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();
}
// Inner classes
The idle object evictor TimerTask
. See Also:
/**
* The idle object evictor {@link TimerTask}.
*
* @see GenericKeyedObjectPool#setTimeBetweenEvictionRunsMillis
*/
class Evictor implements Runnable {
private ScheduledFuture<?> scheduledFuture;
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.
/**
* 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);
}
}
void setScheduledFuture(final ScheduledFuture<?> scheduledFuture) {
this.scheduledFuture = scheduledFuture;
}
void cancel() {
scheduledFuture.cancel(false);
}
}
Maintains a cache of values for a single metric and reports
statistics on the cached values.
/**
* Maintains a cache of values for a single metric and reports
* statistics on the cached values.
*/
private class StatsStore {
private final AtomicLong values[];
private final int size;
private int index;
Create a StatsStore with the given cache size.
Params: - size – number of values to maintain in the cache.
/**
* Create a StatsStore with the given cache size.
*
* @param size number of values to maintain in the cache.
*/
public StatsStore(final int size) {
this.size = size;
values = new AtomicLong[size];
for (int i = 0; i < size; i++) {
values[i] = new AtomicLong(-1);
}
}
Adds a value to the cache. If the cache is full, one of the
existing values is replaced by the new value.
Params: - value – new value to add to the cache.
/**
* 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.
*/
public synchronized void add(final long value) {
values[index].set(value);
index++;
if (index == size) {
index = 0;
}
}
Returns the mean of the cached values.
Returns: the mean of the cache, truncated to long
/**
* Returns 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 != -1) {
counter++;
result = result * ((counter - 1) / (double) counter) +
value/(double) counter;
}
}
return (long) result;
}
@Override
public String toString() {
final StringBuilder builder = new StringBuilder();
builder.append("StatsStore [values=");
builder.append(Arrays.toString(values));
builder.append(", size=");
builder.append(size);
builder.append(", index=");
builder.append(index);
builder.append("]");
return builder.toString();
}
}
The idle object eviction iterator. Holds a reference to the idle objects.
/**
* The idle object eviction iterator. Holds a reference to the idle objects.
*/
class EvictionIterator implements Iterator<PooledObject<T>> {
private final Deque<PooledObject<T>> idleObjects;
private final Iterator<PooledObject<T>> idleObjectIterator;
Create an EvictionIterator for the provided idle instance deque.
Params: - idleObjects – underlying deque
/**
* Create 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();
}
}
Returns the idle object deque referenced by this iterator.
Returns: the idle object deque
/**
* Returns the idle object deque referenced by this iterator.
* @return the idle object deque
*/
public Deque<PooledObject<T>> getIdleObjects() {
return idleObjects;
}
{@inheritDoc} /** {@inheritDoc} */
@Override
public boolean hasNext() {
return idleObjectIterator.hasNext();
}
{@inheritDoc} /** {@inheritDoc} */
@Override
public PooledObject<T> next() {
return idleObjectIterator.next();
}
{@inheritDoc} /** {@inheritDoc} */
@Override
public void remove() {
idleObjectIterator.remove();
}
}
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.
Type parameters: - <T> – type of objects in the pool
/**
* 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 /** Wrapped object */
private final T instance;
Create a wrapper for an instance.
Params: - instance – object to wrap
/**
* Create a wrapper for an instance.
*
* @param instance object to wrap
*/
public IdentityWrapper(final T instance) {
this.instance = instance;
}
@Override
public int hashCode() {
return System.identityHashCode(instance);
}
@Override
@SuppressWarnings("rawtypes")
public boolean equals(final Object other) {
return other instanceof IdentityWrapper &&
((IdentityWrapper) other).instance == instance;
}
Returns: the wrapped object
/**
* @return the wrapped object
*/
public T getObject() {
return instance;
}
@Override
public String toString() {
final StringBuilder builder = new StringBuilder();
builder.append("IdentityWrapper [instance=");
builder.append(instance);
builder.append("]");
return builder.toString();
}
}
@Override
protected void toStringAppendFields(final StringBuilder builder) {
builder.append("maxTotal=");
builder.append(maxTotal);
builder.append(", blockWhenExhausted=");
builder.append(blockWhenExhausted);
builder.append(", maxWaitMillis=");
builder.append(maxWaitMillis);
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(", timeBetweenEvictionRunsMillis=");
builder.append(timeBetweenEvictionRunsMillis);
builder.append(", numTestsPerEvictionRun=");
builder.append(numTestsPerEvictionRun);
builder.append(", minEvictableIdleTimeMillis=");
builder.append(minEvictableIdleTimeMillis);
builder.append(", softMinEvictableIdleTimeMillis=");
builder.append(softMinEvictableIdleTimeMillis);
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(", maxBorrowWaitTimeMillis=");
builder.append(maxBorrowWaitTimeMillis);
builder.append(", swallowedExceptionListener=");
builder.append(swallowedExceptionListener);
}
}