From dev-return-198574-archive-asf-public=cust-asf.ponee.io@tomcat.apache.org Fri May 3 18:41:51 2019
Return-Path:
X-Original-To: archive-asf-public@cust-asf.ponee.io
Delivered-To: archive-asf-public@cust-asf.ponee.io
Received: from mail.apache.org (hermes.apache.org [207.244.88.153])
by mx-eu-01.ponee.io (Postfix) with SMTP id 75D6418064D
for ; Fri, 3 May 2019 20:41:51 +0200 (CEST)
Received: (qmail 43518 invoked by uid 500); 3 May 2019 18:41:47 -0000
Mailing-List: contact dev-help@tomcat.apache.org; run by ezmlm
Precedence: bulk
List-Help:
List-Unsubscribe:
List-Post:
List-Id:
Reply-To: "Tomcat Developers List"
Delivered-To: mailing list dev@tomcat.apache.org
Received: (qmail 43492 invoked by uid 99); 3 May 2019 18:41:47 -0000
Received: from ec2-52-202-80-70.compute-1.amazonaws.com (HELO gitbox.apache.org) (52.202.80.70)
by apache.org (qpsmtpd/0.29) with ESMTP; Fri, 03 May 2019 18:41:47 +0000
Received: by gitbox.apache.org (ASF Mail Server at gitbox.apache.org, from userid 33)
id 1D59C871F9; Fri, 3 May 2019 18:41:47 +0000 (UTC)
Date: Fri, 03 May 2019 18:41:48 +0000
To: "dev@tomcat.apache.org"
Subject: [tomcat] 02/02: Align fork of Commons Pool 2 with the 9.0.x copy
MIME-Version: 1.0
Content-Type: text/plain; charset=utf-8
Content-Transfer-Encoding: 8bit
From: markt@apache.org
In-Reply-To: <155690890658.4465.14518082621035811612@gitbox.apache.org>
References: <155690890658.4465.14518082621035811612@gitbox.apache.org>
X-Git-Host: gitbox.apache.org
X-Git-Repo: tomcat
X-Git-Refname: refs/heads/8.5.x
X-Git-Reftype: branch
X-Git-Rev: 9c27bd13600fa2f6c40bcb6d5ff4ca0f5ca8cafd
X-Git-NotificationType: diff
X-Git-Multimail-Version: 1.5.dev
Auto-Submitted: auto-generated
Message-Id: <20190503184147.1D59C871F9@gitbox.apache.org>
This is an automated email from the ASF dual-hosted git repository.
markt pushed a commit to branch 8.5.x
in repository https://gitbox.apache.org/repos/asf/tomcat.git
commit 9c27bd13600fa2f6c40bcb6d5ff4ca0f5ca8cafd
Author: Mark Thomas
AuthorDate: Fri May 3 19:40:24 2019 +0100
Align fork of Commons Pool 2 with the 9.0.x copy
---
java/org/apache/tomcat/dbcp/pool2/PoolUtils.java | 47 ++++++++++++---------
.../dbcp/pool2/impl/BaseGenericObjectPool.java | 8 ++--
.../tomcat/dbcp/pool2/impl/CallStackUtils.java | 8 +---
.../tomcat/dbcp/pool2/impl/EvictionTimer.java | 35 +++++++++-------
.../dbcp/pool2/impl/GenericKeyedObjectPool.java | 26 ++++++------
.../tomcat/dbcp/pool2/impl/GenericObjectPool.java | 26 ++++++++++++
java/org/apache/tomcat/dbcp/pool2/overview.html | 49 ----------------------
webapps/docs/changelog.xml | 4 ++
8 files changed, 95 insertions(+), 108 deletions(-)
diff --git a/java/org/apache/tomcat/dbcp/pool2/PoolUtils.java b/java/org/apache/tomcat/dbcp/pool2/PoolUtils.java
index 4fb0aba..2494351 100644
--- a/java/org/apache/tomcat/dbcp/pool2/PoolUtils.java
+++ b/java/org/apache/tomcat/dbcp/pool2/PoolUtils.java
@@ -36,6 +36,13 @@ import java.util.concurrent.locks.ReentrantReadWriteLock.WriteLock;
*/
public final class PoolUtils {
+ private static final String MSG_FACTOR_NEGATIVE = "factor must be positive.";
+ private static final String MSG_MIN_IDLE = "minIdle must be non-negative.";
+ private static final String MSG_NULL_KEY = "key must not be null.";
+ private static final String MSG_NULL_KEYED_POOL = "keyedPool must not be null.";
+ private static final String MSG_NULL_KEYS = "keys must not be null.";
+ private static final String MSG_NULL_POOL = "pool must not be null.";
+
/**
* Timer used to periodically check pools idle object count. Because a
* {@link Timer} creates a {@link Thread}, an IODH is used.
@@ -101,10 +108,10 @@ public final class PoolUtils {
final int minIdle, final long period)
throws IllegalArgumentException {
if (pool == null) {
- throw new IllegalArgumentException("keyedPool must not be null.");
+ throw new IllegalArgumentException(MSG_NULL_KEYED_POOL);
}
if (minIdle < 0) {
- throw new IllegalArgumentException("minIdle must be non-negative.");
+ throw new IllegalArgumentException(MSG_MIN_IDLE);
}
final TimerTask task = new ObjectPoolMinIdleTimerTask<>(pool, minIdle);
getMinIdleTimer().schedule(task, 0L, period);
@@ -142,13 +149,13 @@ public final class PoolUtils {
final int minIdle, final long period)
throws IllegalArgumentException {
if (keyedPool == null) {
- throw new IllegalArgumentException("keyedPool must not be null.");
+ throw new IllegalArgumentException(MSG_NULL_KEYED_POOL);
}
if (key == null) {
- throw new IllegalArgumentException("key must not be null.");
+ throw new IllegalArgumentException(MSG_NULL_KEY);
}
if (minIdle < 0) {
- throw new IllegalArgumentException("minIdle must be non-negative.");
+ throw new IllegalArgumentException(MSG_MIN_IDLE);
}
final TimerTask task = new KeyedObjectPoolMinIdleTimerTask<>(
keyedPool, key, minIdle);
@@ -188,7 +195,7 @@ public final class PoolUtils {
final int minIdle, final long period)
throws IllegalArgumentException {
if (keys == null) {
- throw new IllegalArgumentException("keys must not be null.");
+ throw new IllegalArgumentException(MSG_NULL_KEYS);
}
final Map tasks = new HashMap<>(keys.size());
final Iterator iter = keys.iterator();
@@ -217,7 +224,7 @@ public final class PoolUtils {
public static void prefill(final ObjectPool pool, final int count)
throws Exception, IllegalArgumentException {
if (pool == null) {
- throw new IllegalArgumentException("pool must not be null.");
+ throw new IllegalArgumentException(MSG_NULL_POOL);
}
for (int i = 0; i < count; i++) {
pool.addObject();
@@ -246,10 +253,10 @@ public final class PoolUtils {
final K key, final int count) throws Exception,
IllegalArgumentException {
if (keyedPool == null) {
- throw new IllegalArgumentException("keyedPool must not be null.");
+ throw new IllegalArgumentException(MSG_NULL_KEYED_POOL);
}
if (key == null) {
- throw new IllegalArgumentException("key must not be null.");
+ throw new IllegalArgumentException(MSG_NULL_KEY);
}
for (int i = 0; i < count; i++) {
keyedPool.addObject(key);
@@ -281,7 +288,7 @@ public final class PoolUtils {
final Collection keys, final int count) throws Exception,
IllegalArgumentException {
if (keys == null) {
- throw new IllegalArgumentException("keys must not be null.");
+ throw new IllegalArgumentException(MSG_NULL_KEYS);
}
final Iterator iter = keys.iterator();
while (iter.hasNext()) {
@@ -308,7 +315,7 @@ public final class PoolUtils {
*/
public static ObjectPool synchronizedPool(final ObjectPool pool) {
if (pool == null) {
- throw new IllegalArgumentException("pool must not be null.");
+ throw new IllegalArgumentException(MSG_NULL_POOL);
}
/*
* assert !(pool instanceof GenericObjectPool) :
@@ -436,10 +443,10 @@ public final class PoolUtils {
public static ObjectPool erodingPool(final ObjectPool pool,
final float factor) {
if (pool == null) {
- throw new IllegalArgumentException("pool must not be null.");
+ throw new IllegalArgumentException(MSG_NULL_POOL);
}
if (factor <= 0f) {
- throw new IllegalArgumentException("factor must be positive.");
+ throw new IllegalArgumentException(MSG_FACTOR_NEGATIVE);
}
return new ErodingObjectPool<>(pool, factor);
}
@@ -538,10 +545,10 @@ public final class PoolUtils {
final KeyedObjectPool keyedPool, final float factor,
final boolean perKey) {
if (keyedPool == null) {
- throw new IllegalArgumentException("keyedPool must not be null.");
+ throw new IllegalArgumentException(MSG_NULL_KEYED_POOL);
}
if (factor <= 0f) {
- throw new IllegalArgumentException("factor must be positive.");
+ throw new IllegalArgumentException(MSG_FACTOR_NEGATIVE);
}
if (perKey) {
return new ErodingPerKeyKeyedObjectPool<>(keyedPool, factor);
@@ -587,7 +594,7 @@ public final class PoolUtils {
ObjectPoolMinIdleTimerTask(final ObjectPool pool, final int minIdle)
throws IllegalArgumentException {
if (pool == null) {
- throw new IllegalArgumentException("pool must not be null.");
+ throw new IllegalArgumentException(MSG_NULL_POOL);
}
this.pool = pool;
this.minIdle = minIdle;
@@ -665,7 +672,7 @@ public final class PoolUtils {
final K key, final int minIdle) throws IllegalArgumentException {
if (keyedPool == null) {
throw new IllegalArgumentException(
- "keyedPool must not be null.");
+ MSG_NULL_KEYED_POOL);
}
this.keyedPool = keyedPool;
this.key = key;
@@ -747,7 +754,7 @@ public final class PoolUtils {
SynchronizedObjectPool(final ObjectPool pool)
throws IllegalArgumentException {
if (pool == null) {
- throw new IllegalArgumentException("pool must not be null.");
+ throw new IllegalArgumentException(MSG_NULL_POOL);
}
this.pool = pool;
}
@@ -924,7 +931,7 @@ public final class PoolUtils {
throws IllegalArgumentException {
if (keyedPool == null) {
throw new IllegalArgumentException(
- "keyedPool must not be null.");
+ MSG_NULL_KEYED_POOL);
}
this.keyedPool = keyedPool;
}
@@ -1605,7 +1612,7 @@ public final class PoolUtils {
final ErodingFactor erodingFactor) {
if (keyedPool == null) {
throw new IllegalArgumentException(
- "keyedPool must not be null.");
+ MSG_NULL_KEYED_POOL);
}
this.keyedPool = keyedPool;
this.erodingFactor = erodingFactor;
diff --git a/java/org/apache/tomcat/dbcp/pool2/impl/BaseGenericObjectPool.java b/java/org/apache/tomcat/dbcp/pool2/impl/BaseGenericObjectPool.java
index 0de61d6..448c4a7 100644
--- a/java/org/apache/tomcat/dbcp/pool2/impl/BaseGenericObjectPool.java
+++ b/java/org/apache/tomcat/dbcp/pool2/impl/BaseGenericObjectPool.java
@@ -772,11 +772,9 @@ public abstract class BaseGenericObjectPool extends BaseObject {
*/
final void startEvictor(final long delay) {
synchronized (evictionLock) {
- if (null != evictor) {
- EvictionTimer.cancel(evictor, evictorShutdownTimeoutMillis, TimeUnit.MILLISECONDS);
- evictor = null;
- evictionIterator = null;
- }
+ EvictionTimer.cancel(evictor, evictorShutdownTimeoutMillis, TimeUnit.MILLISECONDS);
+ evictor = null;
+ evictionIterator = null;
if (delay > 0) {
evictor = new Evictor();
EvictionTimer.schedule(evictor, delay, delay);
diff --git a/java/org/apache/tomcat/dbcp/pool2/impl/CallStackUtils.java b/java/org/apache/tomcat/dbcp/pool2/impl/CallStackUtils.java
index d5089c3..871f311 100644
--- a/java/org/apache/tomcat/dbcp/pool2/impl/CallStackUtils.java
+++ b/java/org/apache/tomcat/dbcp/pool2/impl/CallStackUtils.java
@@ -25,12 +25,6 @@ import java.security.AccessControlException;
*/
public final class CallStackUtils {
- private static final boolean CAN_CREATE_SECURITY_MANAGER;
-
- static {
- CAN_CREATE_SECURITY_MANAGER = canCreateSecurityManager();
- }
-
/**
* @return {@code true} if it is able to create a security manager in the current environment, {@code false}
* otherwise.
@@ -76,7 +70,7 @@ public final class CallStackUtils {
public static CallStack newCallStack(final String messageFormat,
final boolean useTimestamp,
final boolean requireFullStackTrace) {
- return CAN_CREATE_SECURITY_MANAGER && !requireFullStackTrace
+ return canCreateSecurityManager() && !requireFullStackTrace
? new SecurityManagerCallStack(messageFormat, useTimestamp)
: new ThrowableCallStack(messageFormat, useTimestamp);
}
diff --git a/java/org/apache/tomcat/dbcp/pool2/impl/EvictionTimer.java b/java/org/apache/tomcat/dbcp/pool2/impl/EvictionTimer.java
index b483dc3..f034c38 100644
--- a/java/org/apache/tomcat/dbcp/pool2/impl/EvictionTimer.java
+++ b/java/org/apache/tomcat/dbcp/pool2/impl/EvictionTimer.java
@@ -24,18 +24,20 @@ import java.util.concurrent.ThreadFactory;
import java.util.concurrent.TimeUnit;
/**
- * Provides a shared idle object eviction timer for all pools. This class is
- * currently implemented using {@link ScheduledThreadPoolExecutor}. This
- * implementation may change in any future release. This class keeps track of
- * how many pools are using it. If no pools are using the timer, it is cancelled.
- * This prevents a thread being left running which, in application server
- * environments, can lead to memory leads and/or prevent applications from
- * shutting down or reloading cleanly.
+ * Provides a shared idle object eviction timer for all pools.
*
- * This class has package scope to prevent its inclusion in the pool public API.
- * The class declaration below should *not* be changed to public.
+ * This class is currently implemented using {@link ScheduledThreadPoolExecutor}. This implementation may change in any
+ * future release. This class keeps track of how many pools are using it. If no pools are using the timer, it is
+ * cancelled. This prevents a thread being left running which, in application server environments, can lead to memory
+ * leads and/or prevent applications from shutting down or reloading cleanly.
+ *
+ *
+ * This class has package scope to prevent its inclusion in the pool public API. The class declaration below should
+ * *not* be changed to public.
+ *
*
* This class is intended to be thread-safe.
+ *
*
* @since 2.0
*/
@@ -66,6 +68,7 @@ class EvictionTimer {
* call to this method *must* call {@link #cancel(BaseGenericObjectPool.Evictor,long,TimeUnit)}
* to cancel the task to prevent memory and/or thread leaks in application
* server environments.
+ *
* @param task Task to be scheduled
* @param delay Delay in milliseconds before task is executed
* @param period Time in milliseconds between executions
@@ -84,16 +87,18 @@ class EvictionTimer {
/**
* Remove the specified eviction task from the timer.
*
- * @param task Task to be cancelled
+ * @param evictor Task to be cancelled
* @param timeout If the associated executor is no longer required, how
* long should this thread wait for the executor to
* terminate?
* @param unit The units for the specified timeout
*/
static synchronized void cancel(
- final BaseGenericObjectPool>.Evictor task, final long timeout, final TimeUnit unit) {
- task.cancel();
- if (executor.getQueue().size() == 0) {
+ final BaseGenericObjectPool>.Evictor evictor, final long timeout, final TimeUnit unit) {
+ if (evictor != null) {
+ evictor.cancel();
+ }
+ if (executor != null && executor.getQueue().isEmpty()) {
executor.shutdown();
try {
executor.awaitTermination(timeout, unit);
@@ -107,14 +112,14 @@ class EvictionTimer {
}
/**
- * Thread factory that creates a thread, with the context class loader from this class.
+ * Thread factory that creates a daemon thread, with the context class loader from this class.
*/
private static class EvictorThreadFactory implements ThreadFactory {
@Override
public Thread newThread(final Runnable runnable) {
final Thread thread = new Thread(null, runnable, "commons-pool-evictor-thread");
-
+ thread.setDaemon(true); // POOL-363 - Required for applications using Runtime.addShutdownHook(). --joshlandin 03.27.2019
AccessController.doPrivileged(new PrivilegedAction() {
@Override
public Void run() {
diff --git a/java/org/apache/tomcat/dbcp/pool2/impl/GenericKeyedObjectPool.java b/java/org/apache/tomcat/dbcp/pool2/impl/GenericKeyedObjectPool.java
index d9c9c8f..175631c 100644
--- a/java/org/apache/tomcat/dbcp/pool2/impl/GenericKeyedObjectPool.java
+++ b/java/org/apache/tomcat/dbcp/pool2/impl/GenericKeyedObjectPool.java
@@ -1145,26 +1145,28 @@ public class GenericKeyedObjectPool extends BaseGenericObjectPool
* @param k The key to de-register
*/
private void deregister(final K k) {
+ Lock lock = keyLock.readLock();
ObjectDeque objectDeque;
-
- objectDeque = poolMap.get(k);
- final long numInterested = objectDeque.getNumInterested().decrementAndGet();
- if (numInterested == 0 && objectDeque.getCreateCount().get() == 0) {
- // Potential to remove key
- final Lock writeLock = keyLock.writeLock();
- writeLock.lock();
- try {
- if (objectDeque.getCreateCount().get() == 0 &&
- objectDeque.getNumInterested().get() == 0) {
+ try {
+ lock.lock();
+ objectDeque = poolMap.get(k);
+ final long numInterested = objectDeque.getNumInterested().decrementAndGet();
+ if (numInterested == 0 && objectDeque.getCreateCount().get() == 0) {
+ // Potential to remove key
+ // Upgrade to write lock
+ lock.unlock();
+ lock = keyLock.writeLock();
+ lock.lock();
+ if (objectDeque.getCreateCount().get() == 0 && objectDeque.getNumInterested().get() == 0) {
// NOTE: Keys must always be removed from both poolMap and
// poolKeyList at the same time while protected by
// keyLock.writeLock()
poolMap.remove(k);
poolKeyList.remove(k);
}
- } finally {
- writeLock.unlock();
}
+ } finally {
+ lock.unlock();
}
}
diff --git a/java/org/apache/tomcat/dbcp/pool2/impl/GenericObjectPool.java b/java/org/apache/tomcat/dbcp/pool2/impl/GenericObjectPool.java
index 15b6d6d..04fdd79 100644
--- a/java/org/apache/tomcat/dbcp/pool2/impl/GenericObjectPool.java
+++ b/java/org/apache/tomcat/dbcp/pool2/impl/GenericObjectPool.java
@@ -181,6 +181,7 @@ public class GenericObjectPool extends BaseGenericObjectPool
*
* If the configured value of minIdle is greater than the configured value
* for maxIdle then the value of maxIdle will be used instead.
+ *
*
* @param minIdle
* The minimum number of objects.
@@ -202,6 +203,7 @@ public class GenericObjectPool extends BaseGenericObjectPool
*
* If the configured value of minIdle is greater than the configured value
* for maxIdle then the value of maxIdle will be used instead.
+ *
*
* @return The minimum number of objects.
*
@@ -339,6 +341,7 @@ public class GenericObjectPool extends BaseGenericObjectPool
* borrowObject}({@link #getMaxWaitMillis()}).
*
* {@inheritDoc}
+ *
*/
@Override
public T borrowObject() throws Exception {
@@ -356,6 +359,7 @@ public class GenericObjectPool extends BaseGenericObjectPool
* instance is destroyed and the next available instance is examined. This
* continues until either a valid instance is returned or there are no more
* idle instances available.
+ *
*
* If there are no idle instances available in the pool, behavior depends on
* the {@link #getMaxTotal() maxTotal}, (if applicable)
@@ -365,6 +369,7 @@ public class GenericObjectPool extends BaseGenericObjectPool
* instance is created, activated and (if applicable) validated and returned
* to the caller. If validation fails, a NoSuchElementException
* is thrown.
+ *
*
* If the pool is exhausted (no available idle instances and no capacity to
* create new ones), this method will either block (if
@@ -374,11 +379,13 @@ public class GenericObjectPool extends BaseGenericObjectPool
* method will block when {@link #getBlockWhenExhausted()} is true is
* determined by the value passed in to the borrowMaxWaitMillis
* parameter.
+ *
*
* When the pool is exhausted, multiple calling threads may be
* simultaneously blocked waiting for instances to become available. A
* "fairness" algorithm has been implemented to ensure that threads receive
* available instances in request arrival order.
+ *
*
* @param borrowMaxWaitMillis The time to wait in milliseconds for an object
* to become available
@@ -496,14 +503,17 @@ public class GenericObjectPool extends BaseGenericObjectPool
* If {@link #getMaxIdle() maxIdle} is set to a positive value and the
* number of idle instances has reached this value, the returning instance
* is destroyed.
+ *
*
* If {@link #getTestOnReturn() testOnReturn} == true, the returning
* instance is validated before being returned to the idle instance pool. In
* this case, if validation fails, the instance is destroyed.
+ *
*
* Exceptions encountered destroying objects for any reason are swallowed
* but notified via a
* {@link org.apache.tomcat.dbcp.pool2.SwallowedExceptionListener}.
+ *
*/
@Override
public void returnObject(final T obj) {
@@ -587,6 +597,7 @@ public class GenericObjectPool extends BaseGenericObjectPool
*
* Activation of this method decrements the active count and attempts to
* destroy the instance.
+ *
*
* @throws Exception if an exception occurs destroying the
* object
@@ -617,6 +628,7 @@ public class GenericObjectPool extends BaseGenericObjectPool
* idle instance.
*
* Implementation notes:
+ *
*
* - This method does not destroy or effect in any way instances that are
* checked out of the pool when it is invoked.
@@ -659,6 +671,7 @@ public class GenericObjectPool extends BaseGenericObjectPool
* objects destroyed on return.
*
* Destroys idle instances in the pool by invoking {@link #clear()}.
+ *
*/
@Override
public void close() {
@@ -691,6 +704,7 @@ public class GenericObjectPool extends BaseGenericObjectPool
*
* Successive activations of this method examine objects in sequence,
* cycling through objects in oldest-to-youngest order.
+ *
*/
@Override
public void evict() throws Exception {
@@ -811,6 +825,7 @@ public class GenericObjectPool extends BaseGenericObjectPool
*
* If there are {@link #getMaxTotal()} objects already in circulation
* or in process of being created, this method returns null.
+ *
*
* @return The new wrapped pooled object
*
@@ -915,6 +930,15 @@ public class GenericObjectPool extends BaseGenericObjectPool
destroyedCount.incrementAndGet();
createCount.decrementAndGet();
}
+
+ if (idleObjects.isEmpty() && idleObjects.hasTakeWaiters()) {
+ // POOL-356.
+ // In case there are already threads waiting on something in the pool
+ // (e.g. idleObjects.takeFirst(); then we need to provide them a fresh instance.
+ // Otherwise they will be stuck forever (or until timeout)
+ final PooledObject freshPooled = create();
+ idleObjects.put(freshPooled);
+ }
}
@Override
@@ -929,6 +953,7 @@ public class GenericObjectPool extends BaseGenericObjectPool
* or the total number of objects (idle, checked out, or being created) reaches
* {@link #getMaxTotal()}. If {@code always} is false, no instances are created unless
* there are threads waiting to check out instances from the pool.
+ *
*
* @param idleCount the number of idle instances desired
* @param always true means create instances even if the pool has no threads waiting
@@ -1115,6 +1140,7 @@ public class GenericObjectPool extends BaseGenericObjectPool
* JMX. That means it won't be invoked unless the explicitly requested
* whereas all attributes will be automatically requested when viewing the
* attributes for an object in a tool like JConsole.
+ *
*
* @return Information grouped on all the objects in the pool
*/
diff --git a/java/org/apache/tomcat/dbcp/pool2/overview.html b/java/org/apache/tomcat/dbcp/pool2/overview.html
deleted file mode 100644
index b301d1d..0000000
--- a/java/org/apache/tomcat/dbcp/pool2/overview.html
+++ /dev/null
@@ -1,49 +0,0 @@
-
-
-
- Overview of the org.apache.commons.pool2 component
-
-
-
- Generic Object pooling API with several implementations.
-
-
- The org.apache.commons.pool2
package defines a simple
- interface for a pool of object instances, and a handful of base
- classes that may be useful when creating pool implementations.
- The API supports pooling of unique objects which can be requested
- via a key as well as pools where all objects are equivalent.
-
-
- The org.apache.commons.pool2.impl
package contains
- several pool implementations.
- {@link org.apache.commons.pool2.impl.GenericObjectPool
- GenericObjectPool} has many configuration options and can support
- a limited set of objects such as would be useful in a database
- connection pool.
- {@link org.apache.commons.pool2.impl.SoftReferenceObjectPool
- SoftReferenceObjectPool} has no limit on the number of objects in the
- pool, but the garbage collector can remove idle objects from the pool
- as needed. There is also a keyed version of
- {@link org.apache.commons.pool2.impl.GenericObjectPool
- GenericObjectPool},
- {@link org.apache.commons.pool2.impl.GenericKeyedObjectPool
- GenericKeyedObjectPool}
-
-
-
\ No newline at end of file
diff --git a/webapps/docs/changelog.xml b/webapps/docs/changelog.xml
index 37addb6..565a3ed 100644
--- a/webapps/docs/changelog.xml
+++ b/webapps/docs/changelog.xml
@@ -131,6 +131,10 @@
(2019-04-24) to pick up some clean-up and enhancements less the JDBC 4.2
related changes that require Java 8. (markt)
+
+ Update the internal fork of Apache Commons Pool 2 to 0664f4d
+ (2019-04-30) to pick up some enhancements and bug fixes. (markt)
+
---------------------------------------------------------------------
To unsubscribe, e-mail: dev-unsubscribe@tomcat.apache.org
For additional commands, e-mail: dev-help@tomcat.apache.org