This is an automated email from the ASF dual-hosted git repository.
psteitz pushed a commit to branch POOL_2_X
in repository https://gitbox.apache.org/repos/asf/commons-pool.git
The following commit(s) were added to refs/heads/POOL_2_X by this push:
new c5d63adf Fix for JIRA: POOL-425. Make addObject no-op when maxIdle is
attained.
c5d63adf is described below
commit c5d63adfca0d1063cce6a3a53f4be585cf48c4d1
Author: Phil Steitz <[email protected]>
AuthorDate: Wed Nov 5 20:24:51 2025 -0700
Fix for JIRA: POOL-425. Make addObject no-op when maxIdle is attained.
---
src/changes/changes.xml | 3 ++-
.../commons/pool2/impl/GenericObjectPool.java | 8 +++---
.../commons/pool2/impl/TestGenericObjectPool.java | 29 ++++++++++++++++++++++
3 files changed, 36 insertions(+), 4 deletions(-)
diff --git a/src/changes/changes.xml b/src/changes/changes.xml
index b6865f13..94b76399 100644
--- a/src/changes/changes.xml
+++ b/src/changes/changes.xml
@@ -47,7 +47,8 @@ The <action> type attribute can be add,update,fix,remove.
<body>
<release version="2.13.0" date="YYYY-MM-DD" description="This is a feature
and maintenance release. Java 8 or later is required.">
<!-- FIX -->
- <action type="fix" issue="POOL-350" dev="psteitz" due-to="Phil
Steitz">Make placement of calls to GKOP reuseCapacity configurable.</action>
+ <action type="fix" issue="POOL-425" dev="psteitz">GenericObjectPool
addObject does not respect maxIdle.</action>
+ <action type="fix" issue="POOL-350" dev="psteitz">Make placement of calls
to GKOP reuseCapacity configurable.</action>
<action type="fix" issue="POOL-290" dev="psteitz" due-to="Serge
Angelov">TestSoftRefOutOfMemory (unit test) can loop infinitely on
failure.</action>
<action type="fix" issue="POOL-419" dev="psteitz" due-to="Raju Gupta, Phil
Steitz">GenericObjectPool counters and object collections can be corrupted when
returnObject and invalidate are invoked concurrently by client threads on the
same pooled object.</action>
<action type="fix" issue="POOL-421" dev="psteitz" due-to="Phil
Steitz">GenericObjectPool addObject should return immediately when there is no
capacity to add.</action>
diff --git a/src/main/java/org/apache/commons/pool2/impl/GenericObjectPool.java
b/src/main/java/org/apache/commons/pool2/impl/GenericObjectPool.java
index 15d4d63c..8927e580 100644
--- a/src/main/java/org/apache/commons/pool2/impl/GenericObjectPool.java
+++ b/src/main/java/org/apache/commons/pool2/impl/GenericObjectPool.java
@@ -193,10 +193,11 @@ public class GenericObjectPool<T> extends
BaseGenericObjectPool<T>
}
/**
- * Creates an object, and place it into the pool. addObject() is useful for
+ * Creates an object, and places it into the pool. addObject() is useful
for
* "pre-loading" a pool with idle objects.
* <p>
- * If there is no capacity available to add to the pool, this is a no-op
+ * If there is no capacity available to add to the pool, or there are
already
+ * {@link #getMaxIdle()} idle instances in the pool, this is a no-op
* (no exception, no impact to the pool).
* </p>
* <p>
@@ -213,7 +214,8 @@ public class GenericObjectPool<T> extends
BaseGenericObjectPool<T>
}
final int localMaxTotal = getMaxTotal();
- if (localMaxTotal < 0 || createCount.get() < localMaxTotal) {
+ final int localMaxIdle = getMaxIdle();
+ if (getNumIdle() < localMaxIdle && (localMaxTotal < 0 ||
createCount.get() < localMaxTotal)) {
addIdleObject(create(getMaxWaitDuration()));
}
}
diff --git
a/src/test/java/org/apache/commons/pool2/impl/TestGenericObjectPool.java
b/src/test/java/org/apache/commons/pool2/impl/TestGenericObjectPool.java
index 47c1a1b8..9c9ad43b 100644
--- a/src/test/java/org/apache/commons/pool2/impl/TestGenericObjectPool.java
+++ b/src/test/java/org/apache/commons/pool2/impl/TestGenericObjectPool.java
@@ -750,6 +750,7 @@ class TestGenericObjectPool extends TestBaseObjectPool {
trackerPool.setMaxIdle(-1);
final int instanceCount = 10 + random.nextInt(20);
trackerPool.setMaxTotal(instanceCount);
+ trackerPool.setMaxIdle(instanceCount);
for (int k = 0; k < instanceCount; k++) {
trackerPool.addObject();
}
@@ -2980,4 +2981,32 @@ class TestGenericObjectPool extends TestBaseObjectPool {
assertEquals(1, genericObjectPool.getNumIdle());
genericObjectPool.close();
}
+
+ @Test
+ void testAddObjectRespectsMaxIdle() throws Exception {
+ genericObjectPool.setMaxIdle(1);
+ genericObjectPool.addObject();
+ genericObjectPool.addObject(); // should be no-op
+ assertEquals(1, genericObjectPool.getNumIdle());
+ }
+
+ @Test
+ void testAddObjectRespectsMaxTotal() throws Exception {
+ genericObjectPool.setMaxTotal(1);
+ genericObjectPool.addObject();
+ genericObjectPool.addObject(); // should be no-op
+ assertEquals(1, genericObjectPool.getNumIdle());
+ }
+
+ @Test
+ void testAddObjectCanAddToMaxIdle() throws Exception {
+ genericObjectPool.setMaxTotal(5);
+ genericObjectPool.borrowObject();
+ genericObjectPool.borrowObject();
+ genericObjectPool.setMaxIdle(3);
+ for (int i = 0; i < 3; i++) {
+ genericObjectPool.addObject();
+ }
+ assertEquals(3, genericObjectPool.getNumIdle());
+ }
}