You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@commons.apache.org by gg...@apache.org on 2019/03/13 18:03:42 UTC
[commons-pool] branch master updated: [POOL-362] Always null out
org.apache.commons.pool2.impl.BaseGenericObjectPool.evictionIterator to
match org.apache.commons.pool2.impl.BaseGenericObjectPool.evictor
This is an automated email from the ASF dual-hosted git repository.
ggregory pushed a commit to branch master
in repository https://gitbox.apache.org/repos/asf/commons-pool.git
The following commit(s) were added to refs/heads/master by this push:
new 0187574 [POOL-362] Always null out org.apache.commons.pool2.impl.BaseGenericObjectPool.evictionIterator to match org.apache.commons.pool2.impl.BaseGenericObjectPool.evictor
0187574 is described below
commit 0187574e9cca3ed8c07a989714da922b9697b9a0
Author: Gary Gregory <ga...@gmail.com>
AuthorDate: Wed Mar 13 14:03:39 2019 -0400
[POOL-362] Always null out
org.apache.commons.pool2.impl.BaseGenericObjectPool.evictionIterator to
match org.apache.commons.pool2.impl.BaseGenericObjectPool.evictor
---
src/changes/changes.xml | 1559 +++++------
.../commons/pool2/impl/BaseGenericObjectPool.java | 2824 ++++++++++----------
.../apache/commons/pool2/impl/EvictionTimer.java | 268 +-
3 files changed, 2328 insertions(+), 2323 deletions(-)
diff --git a/src/changes/changes.xml b/src/changes/changes.xml
index 1743a9e..08966f1 100644
--- a/src/changes/changes.xml
+++ b/src/changes/changes.xml
@@ -1,777 +1,782 @@
-<?xml version="1.0"?>
-<!--
- 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.
- -->
-
-<!--
-This file is also used by the maven-changes-plugin to generate the release notes.
-Useful ways of finding items to add to this file are:
-
-1. Add items when you fix a bug or add a feature (this makes the
-release process easy :-).
-
-2. Do a JIRA search for tickets closed since the previous release.
-
-3. Use the report generated by the maven-changelog-plugin to see all
-SVN commits. TBA how to use this with SVN.
-
-To generate the release notes from this file:
-
-mvn changes:announcement-generate -Prelease-notes [-Dchanges.version=nnn]
-
-then tweak the formatting if necessary
-and commit
-
-The <action> type attribute can be add,update,fix,remove.
--->
-
-<document>
- <properties>
- <title>Apache Commons Pool Changes</title>
- </properties>
- <body>
- <release version="2.6.1" date="2019-02-08" description="This is a maintenance release.">
- <action dev="struberg" issue="POOL-340" type="fix" due-to="Pavel Kolesov">
- Correct validateObject with concurrent borrowObject
- </action>
- <action dev="struberg" issue="POOL-356" type="fix">
- Fix deadlock on massive concurrent requests
- </action>
- <action dev="ggregory" issue="POOL-345" type="update">
- Update optional library cglib from 3.2.6 to 3.2.9.
- </action>
- <action dev="ggregory" issue="POOL-346" type="update" due-to="Michael Chen">
- Move common configuration setter to BaseGenericObjectPool #9.
- </action>
- <action dev="ggregory" issue="POOL-347" type="fix" due-to="Shunsuke Nakamura">
- Method borrowObject waits for maxWaitMillis over in pool full.
- </action>
- <action dev="ggregory" issue="POOL-349" type="update">
- Update optional library asm-util from 6.2 to 7.0.
- </action>
- <action dev="ggregory" issue="POOL-359" type="fix" due-to="Michael Wintermeyer, Gary Gregory">
- NullPointerException closing multiple GenericObjectPools.
- </action>
- <action dev="ggregory" issue="POOL-360" type="update">
- Update optional library cglib from 3.2.9 to 3.2.10.
- </action>
- <action dev="ggregory" issue="POOL-326" type="fix" due-to="Chris Allison, Phil Steitz">
- Threading issue, NullPointerException and IllegalStateException in GenericKeyedObjectPool.
- </action>
- <action dev="ggregory" issue="POOL-352" type="fix" due-to="Volker Kleinschmidt, Gary Gregory">
- CallStackUtils mishandles security manager check (partial fix.)
- </action>
- </release>
- <release version="2.6.0" date="2018-07-06" description="This is a maintenance release.">
- <action dev="ggregory" issue="POOL-336" type="update" due-to="Wolfgang Glas">
- GenericObjectPool's borrowObject lock if create() fails with Error.
- </action>
- <action dev="ggregory" issue="POOL-339" type="update">
- Update optional library cglib from 3.2.5 to 3.2.6.
- </action>
- <action dev="markt" issue="POOL-337" type="fix" due-to="Reinald Verheij">
- Ensure cancelled eviction tasks are removed from scheduler.
- </action>
- <action dev="ggregory" issue="POOL-341" type="update">
- Update optional library asm-util from 6.0 to 6.1.1.
- </action>
- <action dev="ggregory" issue="POOL-342" type="update">
- Update optional library asm-util from 6.1.1 to 6.2.
- </action>
- <action dev="ggregory" issue="POOL-338" type="fix" due-to="Michael C, Gary Gregory">
- GenericObjectPool constructor may throw an exception under OSGi.
- </action>
- <action dev="ggregory" issue="POOL-324" type="fix" due-to="Jay Xu, Gary Gregory">
- org.apache.commons.pool2.impl.GenericObjectPool.getFactoryType() throws java.lang.ClassCastException.
- </action>
- <action dev="ggregory" issue="POOL-344" type="fix" due-to="Yulin Wang">
- Delete repeated call startEvictor.
- </action>
- </release>
- <release version="2.5.0" date="2017-12-16" description="This is a minor release, updating to Java 7.">
- <action dev="ggregory" issue="POOL-331" type="update">
- Update from Java 6 to 7.
- </action>
- <action dev="ggregory" issue="POOL-330" type="delete">
- Drop Ant build.
- </action>
- <action dev="ggregory" issue="POOL-332" type="add">
- ObjectPool and KeyedObject pool should extend Closeable.
- </action>
- <action dev="ggregory" issue="POOL-333" type="update">
- Update optional dependency asm-util from 5.2 to 6.0.
- </action>
- <action dev="ggregory" issue="POOL-334" type="update">
- org.apache.commons.pool2.impl.ThrowableCallStack.Snapshot is missing serialVersionUID.
- </action>
- <action dev="mattsicker" issue="POOL-335" type="add">
- Make abandoned logging stack trace requirements configurable. This also reverts
- the default behavior introduced by POOL-320.
- </action>
- <action dev="mattsicker" issue="POOL-335" type="add">
- Make abandoned logging stack trace requirements configurable. This also reverts
- the default behavior introduced by POOL-320.
- </action>
- </release>
- <release version="2.4.3" date="2017-10-24" description="This is a patch release, including bug fixes only.">
- <action dev="ggregory" issue="POOL-328" type="fix" due-to="Lorenzo Solano Martinez">
- Documentation with repeated words (sources, tests, and examples).
- </action>
- <action dev="ggregory" issue="POOL-317" type="fix" due-to="KeiichiFujino">
- Correction of default value of softMinEvictableIdleTimeMillis in BaseObjectPoolConfig.
- </action>
- <action dev="ggregory" issue="POOL-309" type="fix" due-to="jolestar, Roopam Patekar">
- Fix misspellings from "destory" to "destroy".
- </action>
- <action dev="markt" issue="POOL-306" type="fix" due-to="Adrian Crum">
- Ensure BaseGenericObjectPool.IdentityWrapper#equals() follows the expected
- contract for equals().
- </action>
- <action dev="markt" issue="POOL-303" type="fix">
- Ensure that threads do not block indefinitely if more than maxTotal
- threads try to borrow an object at the same time and the factory fails to
- create any objects.
- </action>
- <action dev="markt" issue="POOL-280" type="update" due-to="Jacopo Cappellato">
- Small refactoring of borrowObject() to reduce code duplication.
- </action>
- <action dev="markt" issue="POOL-307" type="update" due-to="Anthony Whitford">
- Replace inefficient use of keySet with entrySet in GKOP.
- </action>
- <action dev="markt" issue="POOL-310" type="fix" due-to="Ivan Iliev">
- Ensure that threads using GKOP do not block indefinitely if more than
- maxTotal threads try to borrow objects with different keys at the same
- time and the factory destroys objects on return.
- </action>
- <action dev="markt" type="fix">
- Ensure that any class name used for evictionPolicyClassName represents a
- class that implements EvictionPolicy.
- </action>
- <action dev="markt" issue="POOL-315" type="fix" due-to="KeiichiFujino">
- Add a configurable delay (default 10 seconds) to wait when shutting down
- an Evictor to allow the associated thread time to complete any current
- evictions and to terminate.
- </action>
- <action dev="markt" type="fix">
- Ensure that a call to GKOP preparePool() takes account of other threads
- that might create objects concurrently, particularly the Evictor.
- </action>
- <action dev="mattsicker" issue="POOL-320" type="add">
- Use more efficient stack walking mechanisms for usage tracking when possible.
- </action>
- <action dev="ggregory" issue="POOL-322" type="update">
- Update optional cglib library from 3.1 to 3.2.5.
- </action>
- <action dev="ggregory" issue="POOL-323" type="update">
- Update optional OW2 ASM from 5.0.4 to 5.2.
- </action>
- </release>
- <release version="2.4.2" date="2015-08-01" description=
- "This is a patch release, including bug fixes only.">
- <action dev="psteitz" issue="POOL-298" type="fix">
- Changed default jmxNameBase in BaseObjectPoolConfig to the correct (null)
- default.
- </action>
- <action dev="psteitz" issue="POOL-300" type="fix">
- Added PrintWriter flush to DefaultPooledObject's printStackTrace method.
- </action>
- </release>
- <release version="2.4.1" date="2015-05-30" description=
- "This is a patch release, replacing a defective binary jar in version 2.4. Other
-than the build configuration, the source distribution for version 2.4.1 is identical
-to version 2.4.">
- <action dev="psteitz" issue="POOL-297" type="fix">
- Reverted cobertura plugin update that caused binary jar corruption.
- </action>
- </release>
- <release version="2.4" date="2015-05-27" description=
- "This is a maintenance release that includes bug fixes and minor enhancements.">
- <action dev="psteitz" type="fix" issue="POOL-287" due-to="Caleb Spare and Thomas Neidhart">
- Fixed capacity leak when an object is offered from a GenericKeyedObjectPool while it is
- being validated by the evictor.
- </action>
- <action dev="psteitz" type="fix" issue="POOL-283">
- Eliminated the requirement that objects managed by GenericObjectPool or
- GenericKeyedObjectPool be discernible by equals. Prior to this fix,
- equal but distinct object instances could not be stored in the same pool.
- </action>
- <action dev="psteitz" type="fix" issue="POOL-284">
- Eliminated the requirement that object equality and hashcodes do not change
- while objects are under management by GenericObjectPool or GenericKeyedObjectPool.
- </action>
- <action dev="markt" type="fix" issue="POOL-289" due-to="Luke Winkenbach">
- Fixed class loading for custom EvictionPolicy implementations that may not
- be present in the class loader hierarchy of the Pool classes by falling
- back to the class loader of the current class.
- </action>
- <action dev="psteitz" type="fix" issue="POOL-285">
- Ensured that when an instance that has already been returned to a pool is
- returned again, the expected IllegalStateException is generated before the
- returning object is re-validated or re-passivated.
- </action>
- <action dev="psteitz" type="add" issue="POOL-286">
- Added preparePool method to GenericObjectPool.
- </action>
- <action dev="ggregory" type="update" issue="POOL-296">
- Update asm-util from 5.0.3 to 5.0.4.
- </action>
- <action dev="psteitz" type="update" issue="POOL-293">
- Exposed getEvictionPolicy as protected in BaseGenericObjectPool.
- </action>
- </release>
- <release version="2.3" date="2014-12-30" description=
-"This is a maintenance release that includes bug fixes and minor enhancements.">
- <action dev="psteitz" type="fix" issue="POOL-279" due-to="Jacopo Cappellato">
- Eliminated possibility that DefaultPoolObject#getIdleTimeMillis() could
- return a negative value. Use by pool implementations would not hit this
- bug.
- </action>
- <action dev="psteitz" type="fix" issue="POOL-275">
- Made wrapped BaseProxyHandler.pooledObject volatile.
- </action>
- <action dev="ecki" type="fix" issue="POOL-277" due-to="Lucas Pouzac">
- Replace synchronisation with lock-free maxBorrowWaitTimeMillis to
- increase scalability.
- </action>
- <action dev="markt" type="fix" issue="POOL-276">
- Ensure that objects are not validated on borrow when testOnBorrow is set
- to false, testOnCreate is set to true and the pool is exhausted at the
- point borrowObject() is called.
- </action>
- <action dev="psteitz" type="fix" issue="POOL-270" due-to="Michael Berman">
- Fixed error in GenericKeyedObjectPool constructor causing minEvictableIdleTimeMillis
- to be used in place of timeBetweenEvictionRunsMillis in eviction timer setup
- when a GenericKeyedObjectPoolConfig instance is supplied to the constructor.
- </action>
- <action dev="markt" type="fix" issue="POOL-263">
- Fix a threading issue that meant that concurrent calls to close() and
- returnObject() could result in some returned objects not being destroyed.
- </action>
- <action dev="psteitz" type="add" issue="POOL-262">
- Made fairness configurable for GenericObjectPool, GenericKeyedObjectPool.
- </action>
- <action dev="markt" type="fix" issue="POOL-261">
- Correctly mark cglib as an optional dependency and ensure that the OSGi
- manifest information reflects that.
- </action>
- <action dev="markt" type="fix">
- Improve performance of statistics collection for pools that extend
- BaseGenericObjectPool.
- </action>
- <action dev="psteitz" type="fix" issue="POOL-259">
- Made client wait time statistics accurate when pools are configured to
- block indefinitely. Also modified computation to include latency clients
- experience due to waiting on factory methods.
- </action>
- <action dev="ggregory" type="update" issue="POOL-273">
- Update cglib to 3.1 from 3.0.
- </action>
- <action dev="ggregory" type="update" issue="POOL-274">
- Update asm-util to 5.0.3 from 4.0.
- </action>
- <action dev="markt" type="fix">
- Prevent potential memory leaks when the Pool is dereferenced without being
- closed.
- </action>
- <action dev="markt" type="fix">
- Prevent potential memory leaks with using an Evictor in a container
- environment.
- </action>
- <action dev="markt" type="fix">
- Protect against a user provided eviction policy throwing an exception and
- stopping the Evictor thread.
- </action>
- <action dev="markt" type="fix">
- Use the thread context class loader to load custom eviction policies. This
- allows application provided eviction policies to be used in a container
- environment when the pooling implementation is provided by the container.
- </action>
- <action dev="markt" type="fix" issue="POOL-281">
- Fix a potential infinite loop in the underlying Deque implementation.
- </action>
- </release>
- <release version="2.2" date="2014-02-24" description=
-"This is a maintenance release that adds a new testOnCreate configuration option
-and fixes a small number of bugs.">
- <action issue="POOL-248" dev="markt" type="fix" due-to="Warren Chen">
- Ensure that if an attempt is made to return an object multiple times that
- the current active and idle object counts are not corrupted.
- </action>
- <action issue="POOL-249" dev="markt" type="fix" due-to="Ville Skyttä">
- Fix Javadoc issues when building docs with Java 8.
- </action>
- <action dev="markt" type="fix">
- Fix the remaining Javadoc warnings.
- </action>
- <action dev="markt" type="add">
- Add a new validation configuration option testOnCreate that tests an
- object immediately after it is created.
- </action>
- </release>
- <release version="2.1" date="2013-12-30" description=
-"This is a maintenance release that includes a small number of new features as well as
-including bugfixes and test case improvements.">
- <action issue="POOL-243" dev="psteitz" type="fix" due-to="Michal Sabo">
- Added missing create counter decrement in GenericKeyedObjectPool create method on factory
- exception path. Prior to this fix, exceptions thrown by factory makeObject calls could leak
- per key capacity.
- </action>
- <action issue="POOL-240" dev="psteitz" type="fix" due-to="Dan McNulty">
- Ensured that blocked threads waiting on a depleted pool get served when
- objects are destroyed due to validation or passivation failures in
- returnObject or when a checked out instance is invalidated.
- </action>
- <action issue="POOL-241" dev="markt" type="add" due-to="Bruno P. Kinoshita">
- Expand the coverage of the unit tests.
- </action>
- <action dev="markt" type="add">
- Provide more control over the names under which Pools are registered in
- JMX so components using the pools can register the pools they use under a
- related name.
- </action>
- <action dev="markt" type="add">
- Include the number of times an object has been borrowed from the Pool when
- the DefaultPooledObject wrapper is used and expose this property via JMX.
- </action>
- <action issue="POOL-245" dev="markt" type="fix" due-to="Bruno P. Kinoshita">
- Remove a duplicate null check and fix some typos in PoolUtils.
- </action>
- <action issue="POOL-246" dev="markt" type="fix" due-to="Bruno P. Kinoshita">
- Make the toString() method of ErodingKeyedObjectPool consistent with the
- other pools.
- </action>
- <action issue="POOL-245" dev="markt" type="add" due-to="Bruno P. Kinoshita">
- Further expansion of the coverage of the unit tests.
- </action>
- </release>
- <release version="2.0" date="2013-11-11" description=
-"This is a major new release that provides significant performance improvements
-in high concurrency environments. Pools now provide a mechanism for tracking
-objects that have been borrowed from the pool but not returned. There have been
-numerous API changes to support these and other new features as well as to
-clarify behaviour and improve consistency across the API. This release requires
-JDK level 1.6 or above.">
- <action issue="POOL-211" dev="markt" type="add" due-to="Brad Koehn">
- Add support for proxy wrappers to ObjectPool and KeyedObjectPool. The
- primary advantage of these wrappers is that use of pooled objects is
- prevented after they have been returned to the pool.
- </action>
- <action issue="POOL-229" dev="psteitz" type="update">
- Added abandoned object removal (moved from DBCP) to GenericObjectPool.
- </action>
- <action issue="POOL-221" dev="markt" type="fix" >
- PooledObject.state does not need to be volatile
- </action>
- <action issue="POOL-220" dev="markt" type="fix">
- Suppress a FindBugs warning
- </action>
- <action issue="POOL-217" dev="markt" type="update" due-to="sebb">
- Use an IODH for PoolUtils.MIN_IDLE_TIMER
- </action>
- <action issue="POOL-216" dev="markt" type="update" >
- GenericKeyedObjectPool.ensureMinIdle(K) does not need to check getMinIdlePerKey().
- </action>
- <action issue="POOL-215" dev="markt" type="fix" >
- GenericKeyedObjectPool - multiple mutable fields not published safely.
- </action>
- <action issue="POOL-214" dev="markt" type="fix" >
- GenericObjectPool.evictionPolicy not thread-safe
- </action>
- <action issue="POOL-212" dev="markt" type="fix" >
- GenericObjectPool allows maxIdle < minIdle
- </action>
- <action issue="POOL-207" dev="markt" type="fix" >
- GenericKeyedObjectPool.clear() has unnecessary null check of objectDequeue
- </action>
- <action issue="POOL-201" dev="markt" type="fix" >
- Classes Generic[Keyed]ObjectPoolConfig are generic - but why?
- </action>
- <action issue="POOL-200" dev="markt" type="fix" >
- GOP/GKOP don't consistently use getters to access fields
- </action>
- <action issue="POOL-199" dev="markt" type="fix" >
- GOP/GKOP evict() method is not synchronised and is not thread-safe
- </action>
- <action issue="POOL-197" dev="markt" type="fix" >
- PooledObject: risky init of lastBorrowTime & lastReturnTime
- </action>
- <action issue="POOL-196" dev="markt" type="fix" >
- PooledObject.getActiveTimeMillis() does not synch. access to lastReturnTime and lastBorrowTime
- </action>
- <action issue="POOL-194" dev="simonetripodi" type="update" date="2011-12-12">
- Replace synchronized blocks in PoolUtils with Read/Write locks.
- </action>
- <action issue="POOL-83" dev="simonetripodi" type="update" date="2011-04-28">
- Support Java 1.5 Generics.
- </action>
- <action issue="POOL-186" dev="simonetripodi" type="update" date="2011-04-28">
- Developer documentation and examples have to be updated once the 2.0 repackaging has been done
- </action>
- <action dev="markt" type="update">
- Switch GOP to use a pooling mechanism based on java.util.concurrent and a
- LinkedBlockingQueue implementation from Apache Harmony (originally by Doug
- Lea and the JSR-166 expert group).
- </action>
- <action dev="markt" type="update">
- Make deprecated protected attributes private, requiring that access is via
- the appropriate getters.
- </action>
- <action dev="markt" type="update">
- Code clean-up. Add missing @Override annotations, remove unused code,
- remove deprecated code and unnecessary code.
- </action>
- <action dev="markt" type="update">
- Introduce an Enum (WhenExhaustedAction) to control pool behaviour when no
- more objects are available to allocate.
- </action>
- <action dev="markt" type="update">
- Remove WhenExhuastedAction.GROW since it is equivalent to
- WhenExhuastedAction.FAIL with a maxActive value of Integer.MAX_VALUE.
- </action>
- <action issue="POOL-188" dev="markt" type="fix" due-to="sebb">
- Remove confusing method PoolUtils.ErodingKeyedObjectPool.numIdle(K key).
- </action>
- <action issue="POOL-155" dev="markt" type="update">
- Guard against multiple returns of the same object to the pool and ensure
- that only objects borrowed from the pool are returned to it.
- </action>
- <action issue="POOL-150" dev="markt" type="fix">
- Ensure GKOP.preparePool() throws an exception if no factory has been
- defined.
- </action>
- <action issue="POOL-134" dev="markt" type="fix">
- Add the ability to specify a per call wait time when borrowing an object.
- </action>
- <action issue="POOL-121" dev="markt" type="fix">
- Provide a name for the eviction timer thread.
- </action>
- <action dev="markt" type="update">
- Remove setFactory() method from GOP.
- </action>
- <action issue="POOL-173" dev="markt" type="fix">
- Reduce duplication in configuration code.
- </action>
- <action issue="POOL-178" dev="markt" type="fix">
- Re-factor common code into common base classes.
- </action>
- <action issue="POOL-172" dev="markt" type="update">
- Expose GOP and GKOP attributes via JMX.
- </action>
- <action issue="POOL-98" dev="markt" type="update">
- Add additional attributes (also accessible via JMX) for monitoring.
- </action>
- <action dev="markt" type="update">
- Change meaning of zero for maxWait to a maximum wait of zero milliseconds
- rather than the unexpected infinite wait.
- </action>
- <action issue="POOL-100" dev="markt" type="fix">
- Allow custom eviction policies to be defined.
- </action>
- <action issue="POOL-211" dev="markt" type="add" due-to="Brad Koehn">
- Add support for proxy wrappers for ObjectPool and KeyedObjectPool. The
- primary advantage of using these wrappers is that use of pooled objects
- is prevented after they have been returned to the pool.
- </action>
- </release>
- <release version="1.6" date="2012-01-07" description="Adds generics and requires Java 5.">
- <action dev="ggregory" type="add" issue="POOL-208">
- Support Java 1.5 Generics in version 1.x.
- </action>
- </release>
- <release version="1.5.7" date="2011-12-20" description="This is a patch release, including bugfixes only.">
- <action dev="psteitz" type="fix" issue="POOL-189" due-to="Bill Speirs">
- Awaken threads waiting on borrowObject when a pool has been closed and have them throw
- IllegalStateException. Prior to the fix for this issue, threads waiting in borrowObject when
- close was invoked on GOP or GKOP would block indefinitely.
- </action>
- <action dev="psteitz" type="fix" issue="POOL-192" due-to="Helge Dannenberg">
- Corrected total internal processing counter update in destroy. Prior to the fix
- for this issue, clear(key) was leaking capacity associated with elements in the
- pool being cleared.
- </action>
- </release>
- <release version="1.5.6" date="2011-04-03" description="This is a patch release, including bugfixes only.">
- <action dev="markt" type="fix" issue="POOL-179" due-to="Axel Grossmann">
- Correctly handle an InterruptedException when waiting for an object from
- the pool.
- </action>
- <action dev="markt" type="fix" issue="POOL-180">
- Only stop tracking objects for a key when there are no idle objects, no
- active objects and no objects being processed.
- </action>
- <action dev="markt" type="update" issue="POOL-181">
- Make BaseObjectPool.isClosed() public.
- </action>
- <action dev="markt" type="fix" issue="POOL-184" due-to="Adrian Nistor">
- Correct bug that could lead to inappropriate pool starvation when evict()
- and borrowObject() are called concurrently.
- </action>
- <action dev="markt" type="fix" due-to="psteitz">
- Fix performance issues when object destruction has latency.
- </action>
- </release>
- <release version="1.5.5" date="2010-09-10" description=
- "This is a patch release, including bugfixes, documentation improvements and some deprecations
- in preparation for pool 2.0.">
- <action dev="psteitz" type="update" issue="POOL-169">
- In preparation for pool 2.0, deprecated direct access to protected fields
- and setFactory methods. In pool 2.0, pool object factories will be immutable.
- </action>
- <action dev="psteitz" type="fix" issue="POOL-158">
- Made GenericKeyedObjectPool._minIdle volatile.
- </action>
- <action dev="markt" type="fix" issue="POOL-161">
- Made the default context class loader for the eviction thread the same loader that loads
- the library to prevent memory leaks in multiple class loader environments.
- </action>
- <action dev="sebb" type="update" issue="POOL-166">
- GenericKeyedObjectPool.destroy could use entrySet() rather than keySet() followed by get()
- </action>
- <action dev="psteitz" type="fix" issue="POOL-157" due-to="David Hu">
- GenericObjectPool and GenericKeyedObjectPool setFactory methods destroy idle instances
- in the pool by contract. Prior to the fix for this issue, newly set factories were being
- used to destroy idle instances, rather than the factories used to create them. The
- setFactory methods have also been deprecated, to be removed in version 2.0.
- </action>
- <action dev="sebb" type="update" issue="POOL-156">
- ObjectPool classes can ignore Throwable. Added consistent handling for Throwables
- that are normally swallowed including always re-throwing certain Throwables (e.g. ThreadDeath).
- </action>
- <action dev="markt" type="fix" issue="POOL-162">
- When waiting threads are interrupted, GOP, GKOP may leak capacity.
- </action>
- <action dev="psteitz" type="fix" issue="POOL-154" due-to="Glen Mazza">
- Documentation for the close method in GenericObjectPool and GenericKeyedObjectPool
- incorrectly states that this method does not clear the pool.
- </action>
- </release>
- <release version="1.5.4" date="2009-11-20" description=
- "This is a patch release containing a fix for POOL-152, a regression
-introduced in version 1.5.">
- <action dev="markt" type="fix" issue="POOL-152" due-to="Bushov Alexander">
- GenericObjectPool can block forever in borrowObject when the pool is exhausted and a newly created
- object fails validation. When borrowing an object if a new object is created but validate fails,
- the latch should not be returned to the queue as an exception will be thrown.
- </action>
- </release>
- <release version="1.5.3" date="2009-09-21" description=
-"This is a patch release containing a fix for POOL-149, a regression
-introduced in version 1.5.">
- <action dev="markt" type="fix" issue="POOL-149" due-to="Shuyang Zhou">
- Fix case where a thread could end up waiting indefinitely even if objects
- were available. Also fixes a couple of leaks in the internal processing
- object count that could lead to pool exhaustion.
- </action>
- </release>
- <release version="1.5.2" date="2009-07-12" description=
-"This is a patch release containing fixes for POOL-146 and POOL-147, regressions
-introduced in version 1.5.">
- <action dev="markt" type="fix" issue="POOL-146">
- Handle the case where one key has reached maxActive but other keys have not.
- Prior to the fix for this issue, threads waiting on objects from keyed pools
- still having instances available could be blocked by a thread requesting an
- instance from an exhausted pool.
- </action>
- <action dev="markt" type="fix" issue="POOL-147" due-to="Giambattista Bloisi">
- Fix case where a thread could end up waiting indefinitely even if objects
- were available.
- </action>
- <action dev="markt" type="fix" issue="POOL-145">
- Ensure that the GenericKeyedObjectPool idle object evictor does not visit the
- same instance more than once per eviction run.
- </action>
- </release>
- <release version="1.5.1" date="2009-06-16" description=
-"This is a patch release containing a fix for POOL-144, a regression introduced
-in version 1.5.">
- <action dev="markt" type="fix" issue="POOL-144">
- When exhausted action is set to WHEN_EXHAUSTED_BLOCK, maxwait is positive and
- client threads time out waiting for idle objects, capacity can be "leaked"
- from GenericObjectPools and GeneritCkeyedObjectPools.
- </action>
- </release>
- <release version="1.5" date="2009-06-10" description=
-"This is a maintenance release including several important bug fixes. This release
-is source and binary compatible with versions 1.3 and 1.4 of commons pool. In addition
-to resolving some important concurrency-related bugs (POOL-135, POOL-125, POOL-29
-POOL-107) this release implements a fairness algorithm to ensure that threads waiting
-for available object instances from GenericObjectPools and GenericKeyedObjectPools are served
-in request arrival order.">
- <action dev="markt" type="fix" issue="POOL-139" due-to="Sebastian Bazley">
- StackKeyedObjectPool.getNumActive() needs to be synchronized.
- </action>
- <action dev="markt" type="fix" issue="POOL-137" due-to="Sebastian Bazley">
- Inconsistent synchronization in GenericObjectPool; constant fields should be final.
- </action>
- <action dev="markt" type="fix" issue="POOL-75" due-to="Takayuki Kaneko and Gordon Mohr">
- GenericObjectPool not FIFO with respect to borrowing threads.
- </action>
- <action dev="markt" type="fix" issue="POOL-135">
- _numActive > _maxActive under load
- </action>
- <action dev="markt" type="fix" issue="POOL-125">
- Insufficient control over concurrent access to pooled objects by Evictor, client threads.
- </action>
- <action dev="markt" type="fix" issue="POOL-107">
- Number of connections created has crossed more than maxActive.
- </action>
- <action dev="markt" type="fix" issue="POOL-122">
- java.util.Timer in EvictionTimer does not recover from OutOfMemoryError in Evictor.
- </action>
- <action dev="markt" type="fix" issue="POOL-133">
- Failed object creation may result in invalid active count in GKOP.
- </action>
- </release>
- <release version="1.4" date="2008-01-15" description=
-"This is a maintenance release including numerous bug fixes. This release
-is source and binary compatible with version 1.3 of commons pool, but
-there are some behavior changes introduced to resolve bugs, remove ambiguity
-or improve robustness. Among these are the change in default behavior of
-GenericObjectPool and GenericKeyedObjectPool from FIFO back to LIFO queues
-(as in 1.2 and earlier). The LIFO/FIFO behavior is now configurable. Some of
-the extra synchronization included in version 1.3 was removed / refactored to
-improve performance. The javadoc has also been made more complete and explicit.
-See the detailed list of changes below for specifics on fixed bugs and behavior
-changes in Commons Pool 1.4. This version of Commons Pool depends only on
-JDK version 1.3 or higher. Classes implementing pools are all intended to be
-threadsafe.">
- <action dev="sandymac" type="fix">
- Fixed constructor which was ignoring maxTotal parameter:
- GenericKeyedObjectPool(KeyedPoolableObjectFactory factory, int maxActive, byte whenExhaustedAction,
- long maxWait, int maxIdle, int maxTotal, boolean testOnBorrow, boolean testOnReturn,
- long timeBetweenEvictionRunsMillis, int numTestsPerEvictionRun, long minEvictableIdleTimeMillis,
- boolean testWhileIdle)
- </action>
- <action dev="sandymac" type="fix">
- Changed StackKeyedObjectPool to discard stalest, not freshest, idle object when maxSleeping is reached.
- </action>
- <action dev="psteitz" type="fix" issue="POOL-102" due-to="John Sumsion">
- Allowed blocked threads in GenericObjectPool borrowObject to be interrupted.
- </action>
- <action dev="psteitz" type="fix" issue="POOL-86">
- Fixes to address idle object eviction and LIFO/FIFO behavior reported
- in POOL-86. Made LIFO/FIFO behavior configurable for GenericObjectPool and
- GenericKeyedObjectPool, with default set back to LIFO (reverting to 1.2 behavior).
- Fixed GOP, GKOP evict method and added tests to ensure objects are visited in
- oldest-to-youngest order. Changed backing store for GOP, GKOP pools back to Commons
- Collections CursorableLinkedList (brought this class in, repackaged with package scope).
- </action>
- <action dev="psteitz" type="fix" issue="POOL-110" due-to="Alexander Pogrebnyak">
- Changed the default setting for Config.softMinEvictableIdleTimeMillis to
- GenericObjectPool.DEFAULT_SOFT_MIN_EVICTABLE_IDLE_TIME_MILLIS (was
- being incorrectly defaulted to DEFAULT_MIN_EVICTABLE_IDLE_TIME_MILLIS).
- </action>
- <action dev="psteitz" type="fix" issue="POOL-97" due-to="Mark Thomas">
- Added a wrapper for the shared idle object eviction timer for all
- pools. The wrapper class wraps the Timer and keeps track of how many
- pools are using it. If no pools are using the timer, it is canceled.
- This prevents a thread being left running which, in application server
- environments, can lead to memory leaks and/or prevent applications
- from shutting down or reloading cleanly.
- </action>
- <action dev="psteitz" type="fix" issue="POOL-93"
- due-to="Mark Thomas">
- Reduced synchronization in GenericObjectPool, GenericKeyedObjectPool.
- Factory method activations within synchronized blocks were causing
- performance problems in DBCP and other applications where factory
- methods could block. Fixes both POOL-93 and POOL-108.
- </action>
- <action dev="psteitz" type="fix" issue="POOL-113">
- Made _testOnBorrow, _testOnReturn volatile and removed synchronization
- in associated getters and setters in GenericObjectPool,
- GenericKeyedObjectPool. Made getNumIdle synchronized in
- StackKeyedObjectPool.
- </action>
- <action dev="psteitz" type="fix" issue="POOL-116">
- Fixed an error in the GenericKeyedObjectPool constructor that takes
- a Config instance as a parameter. The minIdle setting in the Config
- was being ignored by the constructor.
- </action>
- <action def="psteitz" type="fix" issue="POOL-117">
- Made behavior on instance validation failure consistent across pools,
- eliminating possible infinite loops in StackObjectPool,
- StackKeyedObjectPool, SoftReferenceObjectPool when factory fails to
- create valid objects.
- </action>
- <action dev="sandymac" type="update">
- When no factory has been defined, addObject now throws
- IllegalStateExecption instead of NullPointerException for all pools.
- </action>
- <action dev="sandymac" type="update">
- SoftReferenceObjectPool. Improved the accuracy of getNumIdle by
- "pruning" references to objects that have been garbage collected.
- </action>
- <action dev="sandymac" type="update">
- GenericObjectPool, GenericKeyedObjectPool, SoftReferenceObjectPool,
- StackObjectPool. Eliminated IllegalStateExceptions when the following
- operations are attempted on a closed pool: getNumActive, getNumIdle,
- returnObject, invalidateObject. In each case, the operation is allowed
- to proceed, reporting the state of the pool that is being shut down, or
- destroying objects returning to the closed pool.
- </action>
- <action dev="sandymac" type="update">
- StackObjectPool, SoftReferenceObjectPool, GenericKeyedObjectPool. Allowed
- borrowObject to continue (either examining additional idle instances or
- with makeObject) when an exception is encountered activating an idle
- object instead of propagating the exception to the client. Also made
- addObject propagate (not swallow) exceptions when passivating newly
- created instances.
- </action>
- <action dev="psteitz" type="update">
- StackKeyedObjectPool. Added validation check for objects returned
- from borrowObject.
- </action>
- <action dev="sandymac" type="update">
- BaseObjectPool, BaseKeyedObjectPool. Instead of throwing
- UnsupportedOperationException, the base class implementations
- of getNumIdle and getNumActive return negative values. The
- base implementation of close in BaseObjectPool no longer throws
- IllegalStateException when invoked on an already closed pool.
- </action>
-
- </release>
-
- <release version="1.3" date="2006-04-06" description="1.x bugfix release">
- <action type="fix">A large number of bug fixes. See release notes for changes.</action>
- </release>
-
- <release version="1.2" date="2004-06-07" description="bugfixes">
- <action dev="dirkv" type="fix">
- GenericKeyedObjectPoolFactory Config Constructor is incorrect
- </action>
- <action dev="dirkv" type="fix">
- Not possible to extend GenericObjectPool.returnObject() without affecting addObject()
- </action>
- </release>
-
- <release version="1.1" date="2003-10-20" description="bugfixes">
- <action type="fix">A lot of corner cases were fixed</action>
- <action type="fix">Performance improvement by optimizing pool synchronization, the critical code paths were optimized by reducing pool synchronization but we also added more synchronization where needed</action>
- <action type="fix">New minIdle feature: the minimum number of objects allowed in the pool before the evictor thread (if active) spawns new objects. (Note no objects are created when: numActive + numIdle >= maxActive)</action>
- <action type="fix">New maxTotal feature: a cap on the total number of instances controlled by a pool. Only for GenericKeyedObjectPool where maxActive is a cap on the number of active instances from the pool (per key).</action>
- <action type="fix">UML Class and sequence diagrams</action>
- <action type="fix">See bugzilla for more changes</action>
- </release>
-
- <release version="1.0.1" date="2002-08-12">
- <action type="fix">No change log available.</action>
- </release>
-
- <release version="1.0" date="2002-05-04">
- <action type="add">No change log available.</action>
- </release>
- </body>
-</document>
+<?xml version="1.0"?>
+<!--
+ 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.
+ -->
+
+<!--
+This file is also used by the maven-changes-plugin to generate the release notes.
+Useful ways of finding items to add to this file are:
+
+1. Add items when you fix a bug or add a feature (this makes the
+release process easy :-).
+
+2. Do a JIRA search for tickets closed since the previous release.
+
+3. Use the report generated by the maven-changelog-plugin to see all
+SVN commits. TBA how to use this with SVN.
+
+To generate the release notes from this file:
+
+mvn changes:announcement-generate -Prelease-notes [-Dchanges.version=nnn]
+
+then tweak the formatting if necessary
+and commit
+
+The <action> type attribute can be add,update,fix,remove.
+-->
+
+<document>
+ <properties>
+ <title>Apache Commons Pool Changes</title>
+ </properties>
+ <body>
+ <release version="2.6.2" date="2019-MM-DD" description="This is a maintenance release.">
+ <action dev="ggregory" issue="POOL-362" type="fix">
+ Always null out org.apache.commons.pool2.impl.BaseGenericObjectPool.evictionIterator to match org.apache.commons.pool2.impl.BaseGenericObjectPool.evictor.
+ </action>
+ </release>
+ <release version="2.6.1" date="2019-02-08" description="This is a maintenance release.">
+ <action dev="struberg" issue="POOL-340" type="fix" due-to="Pavel Kolesov">
+ Correct validateObject with concurrent borrowObject
+ </action>
+ <action dev="struberg" issue="POOL-356" type="fix">
+ Fix deadlock on massive concurrent requests
+ </action>
+ <action dev="ggregory" issue="POOL-345" type="update">
+ Update optional library cglib from 3.2.6 to 3.2.9.
+ </action>
+ <action dev="ggregory" issue="POOL-346" type="update" due-to="Michael Chen">
+ Move common configuration setter to BaseGenericObjectPool #9.
+ </action>
+ <action dev="ggregory" issue="POOL-347" type="fix" due-to="Shunsuke Nakamura">
+ Method borrowObject waits for maxWaitMillis over in pool full.
+ </action>
+ <action dev="ggregory" issue="POOL-349" type="update">
+ Update optional library asm-util from 6.2 to 7.0.
+ </action>
+ <action dev="ggregory" issue="POOL-359" type="fix" due-to="Michael Wintermeyer, Gary Gregory">
+ NullPointerException closing multiple GenericObjectPools.
+ </action>
+ <action dev="ggregory" issue="POOL-360" type="update">
+ Update optional library cglib from 3.2.9 to 3.2.10.
+ </action>
+ <action dev="ggregory" issue="POOL-326" type="fix" due-to="Chris Allison, Phil Steitz">
+ Threading issue, NullPointerException and IllegalStateException in GenericKeyedObjectPool.
+ </action>
+ <action dev="ggregory" issue="POOL-352" type="fix" due-to="Volker Kleinschmidt, Gary Gregory">
+ CallStackUtils mishandles security manager check (partial fix.)
+ </action>
+ </release>
+ <release version="2.6.0" date="2018-07-06" description="This is a maintenance release.">
+ <action dev="ggregory" issue="POOL-336" type="update" due-to="Wolfgang Glas">
+ GenericObjectPool's borrowObject lock if create() fails with Error.
+ </action>
+ <action dev="ggregory" issue="POOL-339" type="update">
+ Update optional library cglib from 3.2.5 to 3.2.6.
+ </action>
+ <action dev="markt" issue="POOL-337" type="fix" due-to="Reinald Verheij">
+ Ensure cancelled eviction tasks are removed from scheduler.
+ </action>
+ <action dev="ggregory" issue="POOL-341" type="update">
+ Update optional library asm-util from 6.0 to 6.1.1.
+ </action>
+ <action dev="ggregory" issue="POOL-342" type="update">
+ Update optional library asm-util from 6.1.1 to 6.2.
+ </action>
+ <action dev="ggregory" issue="POOL-338" type="fix" due-to="Michael C, Gary Gregory">
+ GenericObjectPool constructor may throw an exception under OSGi.
+ </action>
+ <action dev="ggregory" issue="POOL-324" type="fix" due-to="Jay Xu, Gary Gregory">
+ org.apache.commons.pool2.impl.GenericObjectPool.getFactoryType() throws java.lang.ClassCastException.
+ </action>
+ <action dev="ggregory" issue="POOL-344" type="fix" due-to="Yulin Wang">
+ Delete repeated call startEvictor.
+ </action>
+ </release>
+ <release version="2.5.0" date="2017-12-16" description="This is a minor release, updating to Java 7.">
+ <action dev="ggregory" issue="POOL-331" type="update">
+ Update from Java 6 to 7.
+ </action>
+ <action dev="ggregory" issue="POOL-330" type="delete">
+ Drop Ant build.
+ </action>
+ <action dev="ggregory" issue="POOL-332" type="add">
+ ObjectPool and KeyedObject pool should extend Closeable.
+ </action>
+ <action dev="ggregory" issue="POOL-333" type="update">
+ Update optional dependency asm-util from 5.2 to 6.0.
+ </action>
+ <action dev="ggregory" issue="POOL-334" type="update">
+ org.apache.commons.pool2.impl.ThrowableCallStack.Snapshot is missing serialVersionUID.
+ </action>
+ <action dev="mattsicker" issue="POOL-335" type="add">
+ Make abandoned logging stack trace requirements configurable. This also reverts
+ the default behavior introduced by POOL-320.
+ </action>
+ <action dev="mattsicker" issue="POOL-335" type="add">
+ Make abandoned logging stack trace requirements configurable. This also reverts
+ the default behavior introduced by POOL-320.
+ </action>
+ </release>
+ <release version="2.4.3" date="2017-10-24" description="This is a patch release, including bug fixes only.">
+ <action dev="ggregory" issue="POOL-328" type="fix" due-to="Lorenzo Solano Martinez">
+ Documentation with repeated words (sources, tests, and examples).
+ </action>
+ <action dev="ggregory" issue="POOL-317" type="fix" due-to="KeiichiFujino">
+ Correction of default value of softMinEvictableIdleTimeMillis in BaseObjectPoolConfig.
+ </action>
+ <action dev="ggregory" issue="POOL-309" type="fix" due-to="jolestar, Roopam Patekar">
+ Fix misspellings from "destory" to "destroy".
+ </action>
+ <action dev="markt" issue="POOL-306" type="fix" due-to="Adrian Crum">
+ Ensure BaseGenericObjectPool.IdentityWrapper#equals() follows the expected
+ contract for equals().
+ </action>
+ <action dev="markt" issue="POOL-303" type="fix">
+ Ensure that threads do not block indefinitely if more than maxTotal
+ threads try to borrow an object at the same time and the factory fails to
+ create any objects.
+ </action>
+ <action dev="markt" issue="POOL-280" type="update" due-to="Jacopo Cappellato">
+ Small refactoring of borrowObject() to reduce code duplication.
+ </action>
+ <action dev="markt" issue="POOL-307" type="update" due-to="Anthony Whitford">
+ Replace inefficient use of keySet with entrySet in GKOP.
+ </action>
+ <action dev="markt" issue="POOL-310" type="fix" due-to="Ivan Iliev">
+ Ensure that threads using GKOP do not block indefinitely if more than
+ maxTotal threads try to borrow objects with different keys at the same
+ time and the factory destroys objects on return.
+ </action>
+ <action dev="markt" type="fix">
+ Ensure that any class name used for evictionPolicyClassName represents a
+ class that implements EvictionPolicy.
+ </action>
+ <action dev="markt" issue="POOL-315" type="fix" due-to="KeiichiFujino">
+ Add a configurable delay (default 10 seconds) to wait when shutting down
+ an Evictor to allow the associated thread time to complete any current
+ evictions and to terminate.
+ </action>
+ <action dev="markt" type="fix">
+ Ensure that a call to GKOP preparePool() takes account of other threads
+ that might create objects concurrently, particularly the Evictor.
+ </action>
+ <action dev="mattsicker" issue="POOL-320" type="add">
+ Use more efficient stack walking mechanisms for usage tracking when possible.
+ </action>
+ <action dev="ggregory" issue="POOL-322" type="update">
+ Update optional cglib library from 3.1 to 3.2.5.
+ </action>
+ <action dev="ggregory" issue="POOL-323" type="update">
+ Update optional OW2 ASM from 5.0.4 to 5.2.
+ </action>
+ </release>
+ <release version="2.4.2" date="2015-08-01" description=
+ "This is a patch release, including bug fixes only.">
+ <action dev="psteitz" issue="POOL-298" type="fix">
+ Changed default jmxNameBase in BaseObjectPoolConfig to the correct (null)
+ default.
+ </action>
+ <action dev="psteitz" issue="POOL-300" type="fix">
+ Added PrintWriter flush to DefaultPooledObject's printStackTrace method.
+ </action>
+ </release>
+ <release version="2.4.1" date="2015-05-30" description=
+ "This is a patch release, replacing a defective binary jar in version 2.4. Other
+than the build configuration, the source distribution for version 2.4.1 is identical
+to version 2.4.">
+ <action dev="psteitz" issue="POOL-297" type="fix">
+ Reverted cobertura plugin update that caused binary jar corruption.
+ </action>
+ </release>
+ <release version="2.4" date="2015-05-27" description=
+ "This is a maintenance release that includes bug fixes and minor enhancements.">
+ <action dev="psteitz" type="fix" issue="POOL-287" due-to="Caleb Spare and Thomas Neidhart">
+ Fixed capacity leak when an object is offered from a GenericKeyedObjectPool while it is
+ being validated by the evictor.
+ </action>
+ <action dev="psteitz" type="fix" issue="POOL-283">
+ Eliminated the requirement that objects managed by GenericObjectPool or
+ GenericKeyedObjectPool be discernible by equals. Prior to this fix,
+ equal but distinct object instances could not be stored in the same pool.
+ </action>
+ <action dev="psteitz" type="fix" issue="POOL-284">
+ Eliminated the requirement that object equality and hashcodes do not change
+ while objects are under management by GenericObjectPool or GenericKeyedObjectPool.
+ </action>
+ <action dev="markt" type="fix" issue="POOL-289" due-to="Luke Winkenbach">
+ Fixed class loading for custom EvictionPolicy implementations that may not
+ be present in the class loader hierarchy of the Pool classes by falling
+ back to the class loader of the current class.
+ </action>
+ <action dev="psteitz" type="fix" issue="POOL-285">
+ Ensured that when an instance that has already been returned to a pool is
+ returned again, the expected IllegalStateException is generated before the
+ returning object is re-validated or re-passivated.
+ </action>
+ <action dev="psteitz" type="add" issue="POOL-286">
+ Added preparePool method to GenericObjectPool.
+ </action>
+ <action dev="ggregory" type="update" issue="POOL-296">
+ Update asm-util from 5.0.3 to 5.0.4.
+ </action>
+ <action dev="psteitz" type="update" issue="POOL-293">
+ Exposed getEvictionPolicy as protected in BaseGenericObjectPool.
+ </action>
+ </release>
+ <release version="2.3" date="2014-12-30" description=
+"This is a maintenance release that includes bug fixes and minor enhancements.">
+ <action dev="psteitz" type="fix" issue="POOL-279" due-to="Jacopo Cappellato">
+ Eliminated possibility that DefaultPoolObject#getIdleTimeMillis() could
+ return a negative value. Use by pool implementations would not hit this
+ bug.
+ </action>
+ <action dev="psteitz" type="fix" issue="POOL-275">
+ Made wrapped BaseProxyHandler.pooledObject volatile.
+ </action>
+ <action dev="ecki" type="fix" issue="POOL-277" due-to="Lucas Pouzac">
+ Replace synchronisation with lock-free maxBorrowWaitTimeMillis to
+ increase scalability.
+ </action>
+ <action dev="markt" type="fix" issue="POOL-276">
+ Ensure that objects are not validated on borrow when testOnBorrow is set
+ to false, testOnCreate is set to true and the pool is exhausted at the
+ point borrowObject() is called.
+ </action>
+ <action dev="psteitz" type="fix" issue="POOL-270" due-to="Michael Berman">
+ Fixed error in GenericKeyedObjectPool constructor causing minEvictableIdleTimeMillis
+ to be used in place of timeBetweenEvictionRunsMillis in eviction timer setup
+ when a GenericKeyedObjectPoolConfig instance is supplied to the constructor.
+ </action>
+ <action dev="markt" type="fix" issue="POOL-263">
+ Fix a threading issue that meant that concurrent calls to close() and
+ returnObject() could result in some returned objects not being destroyed.
+ </action>
+ <action dev="psteitz" type="add" issue="POOL-262">
+ Made fairness configurable for GenericObjectPool, GenericKeyedObjectPool.
+ </action>
+ <action dev="markt" type="fix" issue="POOL-261">
+ Correctly mark cglib as an optional dependency and ensure that the OSGi
+ manifest information reflects that.
+ </action>
+ <action dev="markt" type="fix">
+ Improve performance of statistics collection for pools that extend
+ BaseGenericObjectPool.
+ </action>
+ <action dev="psteitz" type="fix" issue="POOL-259">
+ Made client wait time statistics accurate when pools are configured to
+ block indefinitely. Also modified computation to include latency clients
+ experience due to waiting on factory methods.
+ </action>
+ <action dev="ggregory" type="update" issue="POOL-273">
+ Update cglib to 3.1 from 3.0.
+ </action>
+ <action dev="ggregory" type="update" issue="POOL-274">
+ Update asm-util to 5.0.3 from 4.0.
+ </action>
+ <action dev="markt" type="fix">
+ Prevent potential memory leaks when the Pool is dereferenced without being
+ closed.
+ </action>
+ <action dev="markt" type="fix">
+ Prevent potential memory leaks with using an Evictor in a container
+ environment.
+ </action>
+ <action dev="markt" type="fix">
+ Protect against a user provided eviction policy throwing an exception and
+ stopping the Evictor thread.
+ </action>
+ <action dev="markt" type="fix">
+ Use the thread context class loader to load custom eviction policies. This
+ allows application provided eviction policies to be used in a container
+ environment when the pooling implementation is provided by the container.
+ </action>
+ <action dev="markt" type="fix" issue="POOL-281">
+ Fix a potential infinite loop in the underlying Deque implementation.
+ </action>
+ </release>
+ <release version="2.2" date="2014-02-24" description=
+"This is a maintenance release that adds a new testOnCreate configuration option
+and fixes a small number of bugs.">
+ <action issue="POOL-248" dev="markt" type="fix" due-to="Warren Chen">
+ Ensure that if an attempt is made to return an object multiple times that
+ the current active and idle object counts are not corrupted.
+ </action>
+ <action issue="POOL-249" dev="markt" type="fix" due-to="Ville Skyttä">
+ Fix Javadoc issues when building docs with Java 8.
+ </action>
+ <action dev="markt" type="fix">
+ Fix the remaining Javadoc warnings.
+ </action>
+ <action dev="markt" type="add">
+ Add a new validation configuration option testOnCreate that tests an
+ object immediately after it is created.
+ </action>
+ </release>
+ <release version="2.1" date="2013-12-30" description=
+"This is a maintenance release that includes a small number of new features as well as
+including bugfixes and test case improvements.">
+ <action issue="POOL-243" dev="psteitz" type="fix" due-to="Michal Sabo">
+ Added missing create counter decrement in GenericKeyedObjectPool create method on factory
+ exception path. Prior to this fix, exceptions thrown by factory makeObject calls could leak
+ per key capacity.
+ </action>
+ <action issue="POOL-240" dev="psteitz" type="fix" due-to="Dan McNulty">
+ Ensured that blocked threads waiting on a depleted pool get served when
+ objects are destroyed due to validation or passivation failures in
+ returnObject or when a checked out instance is invalidated.
+ </action>
+ <action issue="POOL-241" dev="markt" type="add" due-to="Bruno P. Kinoshita">
+ Expand the coverage of the unit tests.
+ </action>
+ <action dev="markt" type="add">
+ Provide more control over the names under which Pools are registered in
+ JMX so components using the pools can register the pools they use under a
+ related name.
+ </action>
+ <action dev="markt" type="add">
+ Include the number of times an object has been borrowed from the Pool when
+ the DefaultPooledObject wrapper is used and expose this property via JMX.
+ </action>
+ <action issue="POOL-245" dev="markt" type="fix" due-to="Bruno P. Kinoshita">
+ Remove a duplicate null check and fix some typos in PoolUtils.
+ </action>
+ <action issue="POOL-246" dev="markt" type="fix" due-to="Bruno P. Kinoshita">
+ Make the toString() method of ErodingKeyedObjectPool consistent with the
+ other pools.
+ </action>
+ <action issue="POOL-245" dev="markt" type="add" due-to="Bruno P. Kinoshita">
+ Further expansion of the coverage of the unit tests.
+ </action>
+ </release>
+ <release version="2.0" date="2013-11-11" description=
+"This is a major new release that provides significant performance improvements
+in high concurrency environments. Pools now provide a mechanism for tracking
+objects that have been borrowed from the pool but not returned. There have been
+numerous API changes to support these and other new features as well as to
+clarify behaviour and improve consistency across the API. This release requires
+JDK level 1.6 or above.">
+ <action issue="POOL-211" dev="markt" type="add" due-to="Brad Koehn">
+ Add support for proxy wrappers to ObjectPool and KeyedObjectPool. The
+ primary advantage of these wrappers is that use of pooled objects is
+ prevented after they have been returned to the pool.
+ </action>
+ <action issue="POOL-229" dev="psteitz" type="update">
+ Added abandoned object removal (moved from DBCP) to GenericObjectPool.
+ </action>
+ <action issue="POOL-221" dev="markt" type="fix" >
+ PooledObject.state does not need to be volatile
+ </action>
+ <action issue="POOL-220" dev="markt" type="fix">
+ Suppress a FindBugs warning
+ </action>
+ <action issue="POOL-217" dev="markt" type="update" due-to="sebb">
+ Use an IODH for PoolUtils.MIN_IDLE_TIMER
+ </action>
+ <action issue="POOL-216" dev="markt" type="update" >
+ GenericKeyedObjectPool.ensureMinIdle(K) does not need to check getMinIdlePerKey().
+ </action>
+ <action issue="POOL-215" dev="markt" type="fix" >
+ GenericKeyedObjectPool - multiple mutable fields not published safely.
+ </action>
+ <action issue="POOL-214" dev="markt" type="fix" >
+ GenericObjectPool.evictionPolicy not thread-safe
+ </action>
+ <action issue="POOL-212" dev="markt" type="fix" >
+ GenericObjectPool allows maxIdle < minIdle
+ </action>
+ <action issue="POOL-207" dev="markt" type="fix" >
+ GenericKeyedObjectPool.clear() has unnecessary null check of objectDequeue
+ </action>
+ <action issue="POOL-201" dev="markt" type="fix" >
+ Classes Generic[Keyed]ObjectPoolConfig are generic - but why?
+ </action>
+ <action issue="POOL-200" dev="markt" type="fix" >
+ GOP/GKOP don't consistently use getters to access fields
+ </action>
+ <action issue="POOL-199" dev="markt" type="fix" >
+ GOP/GKOP evict() method is not synchronised and is not thread-safe
+ </action>
+ <action issue="POOL-197" dev="markt" type="fix" >
+ PooledObject: risky init of lastBorrowTime & lastReturnTime
+ </action>
+ <action issue="POOL-196" dev="markt" type="fix" >
+ PooledObject.getActiveTimeMillis() does not synch. access to lastReturnTime and lastBorrowTime
+ </action>
+ <action issue="POOL-194" dev="simonetripodi" type="update" date="2011-12-12">
+ Replace synchronized blocks in PoolUtils with Read/Write locks.
+ </action>
+ <action issue="POOL-83" dev="simonetripodi" type="update" date="2011-04-28">
+ Support Java 1.5 Generics.
+ </action>
+ <action issue="POOL-186" dev="simonetripodi" type="update" date="2011-04-28">
+ Developer documentation and examples have to be updated once the 2.0 repackaging has been done
+ </action>
+ <action dev="markt" type="update">
+ Switch GOP to use a pooling mechanism based on java.util.concurrent and a
+ LinkedBlockingQueue implementation from Apache Harmony (originally by Doug
+ Lea and the JSR-166 expert group).
+ </action>
+ <action dev="markt" type="update">
+ Make deprecated protected attributes private, requiring that access is via
+ the appropriate getters.
+ </action>
+ <action dev="markt" type="update">
+ Code clean-up. Add missing @Override annotations, remove unused code,
+ remove deprecated code and unnecessary code.
+ </action>
+ <action dev="markt" type="update">
+ Introduce an Enum (WhenExhaustedAction) to control pool behaviour when no
+ more objects are available to allocate.
+ </action>
+ <action dev="markt" type="update">
+ Remove WhenExhuastedAction.GROW since it is equivalent to
+ WhenExhuastedAction.FAIL with a maxActive value of Integer.MAX_VALUE.
+ </action>
+ <action issue="POOL-188" dev="markt" type="fix" due-to="sebb">
+ Remove confusing method PoolUtils.ErodingKeyedObjectPool.numIdle(K key).
+ </action>
+ <action issue="POOL-155" dev="markt" type="update">
+ Guard against multiple returns of the same object to the pool and ensure
+ that only objects borrowed from the pool are returned to it.
+ </action>
+ <action issue="POOL-150" dev="markt" type="fix">
+ Ensure GKOP.preparePool() throws an exception if no factory has been
+ defined.
+ </action>
+ <action issue="POOL-134" dev="markt" type="fix">
+ Add the ability to specify a per call wait time when borrowing an object.
+ </action>
+ <action issue="POOL-121" dev="markt" type="fix">
+ Provide a name for the eviction timer thread.
+ </action>
+ <action dev="markt" type="update">
+ Remove setFactory() method from GOP.
+ </action>
+ <action issue="POOL-173" dev="markt" type="fix">
+ Reduce duplication in configuration code.
+ </action>
+ <action issue="POOL-178" dev="markt" type="fix">
+ Re-factor common code into common base classes.
+ </action>
+ <action issue="POOL-172" dev="markt" type="update">
+ Expose GOP and GKOP attributes via JMX.
+ </action>
+ <action issue="POOL-98" dev="markt" type="update">
+ Add additional attributes (also accessible via JMX) for monitoring.
+ </action>
+ <action dev="markt" type="update">
+ Change meaning of zero for maxWait to a maximum wait of zero milliseconds
+ rather than the unexpected infinite wait.
+ </action>
+ <action issue="POOL-100" dev="markt" type="fix">
+ Allow custom eviction policies to be defined.
+ </action>
+ <action issue="POOL-211" dev="markt" type="add" due-to="Brad Koehn">
+ Add support for proxy wrappers for ObjectPool and KeyedObjectPool. The
+ primary advantage of using these wrappers is that use of pooled objects
+ is prevented after they have been returned to the pool.
+ </action>
+ </release>
+ <release version="1.6" date="2012-01-07" description="Adds generics and requires Java 5.">
+ <action dev="ggregory" type="add" issue="POOL-208">
+ Support Java 1.5 Generics in version 1.x.
+ </action>
+ </release>
+ <release version="1.5.7" date="2011-12-20" description="This is a patch release, including bugfixes only.">
+ <action dev="psteitz" type="fix" issue="POOL-189" due-to="Bill Speirs">
+ Awaken threads waiting on borrowObject when a pool has been closed and have them throw
+ IllegalStateException. Prior to the fix for this issue, threads waiting in borrowObject when
+ close was invoked on GOP or GKOP would block indefinitely.
+ </action>
+ <action dev="psteitz" type="fix" issue="POOL-192" due-to="Helge Dannenberg">
+ Corrected total internal processing counter update in destroy. Prior to the fix
+ for this issue, clear(key) was leaking capacity associated with elements in the
+ pool being cleared.
+ </action>
+ </release>
+ <release version="1.5.6" date="2011-04-03" description="This is a patch release, including bugfixes only.">
+ <action dev="markt" type="fix" issue="POOL-179" due-to="Axel Grossmann">
+ Correctly handle an InterruptedException when waiting for an object from
+ the pool.
+ </action>
+ <action dev="markt" type="fix" issue="POOL-180">
+ Only stop tracking objects for a key when there are no idle objects, no
+ active objects and no objects being processed.
+ </action>
+ <action dev="markt" type="update" issue="POOL-181">
+ Make BaseObjectPool.isClosed() public.
+ </action>
+ <action dev="markt" type="fix" issue="POOL-184" due-to="Adrian Nistor">
+ Correct bug that could lead to inappropriate pool starvation when evict()
+ and borrowObject() are called concurrently.
+ </action>
+ <action dev="markt" type="fix" due-to="psteitz">
+ Fix performance issues when object destruction has latency.
+ </action>
+ </release>
+ <release version="1.5.5" date="2010-09-10" description=
+ "This is a patch release, including bugfixes, documentation improvements and some deprecations
+ in preparation for pool 2.0.">
+ <action dev="psteitz" type="update" issue="POOL-169">
+ In preparation for pool 2.0, deprecated direct access to protected fields
+ and setFactory methods. In pool 2.0, pool object factories will be immutable.
+ </action>
+ <action dev="psteitz" type="fix" issue="POOL-158">
+ Made GenericKeyedObjectPool._minIdle volatile.
+ </action>
+ <action dev="markt" type="fix" issue="POOL-161">
+ Made the default context class loader for the eviction thread the same loader that loads
+ the library to prevent memory leaks in multiple class loader environments.
+ </action>
+ <action dev="sebb" type="update" issue="POOL-166">
+ GenericKeyedObjectPool.destroy could use entrySet() rather than keySet() followed by get()
+ </action>
+ <action dev="psteitz" type="fix" issue="POOL-157" due-to="David Hu">
+ GenericObjectPool and GenericKeyedObjectPool setFactory methods destroy idle instances
+ in the pool by contract. Prior to the fix for this issue, newly set factories were being
+ used to destroy idle instances, rather than the factories used to create them. The
+ setFactory methods have also been deprecated, to be removed in version 2.0.
+ </action>
+ <action dev="sebb" type="update" issue="POOL-156">
+ ObjectPool classes can ignore Throwable. Added consistent handling for Throwables
+ that are normally swallowed including always re-throwing certain Throwables (e.g. ThreadDeath).
+ </action>
+ <action dev="markt" type="fix" issue="POOL-162">
+ When waiting threads are interrupted, GOP, GKOP may leak capacity.
+ </action>
+ <action dev="psteitz" type="fix" issue="POOL-154" due-to="Glen Mazza">
+ Documentation for the close method in GenericObjectPool and GenericKeyedObjectPool
+ incorrectly states that this method does not clear the pool.
+ </action>
+ </release>
+ <release version="1.5.4" date="2009-11-20" description=
+ "This is a patch release containing a fix for POOL-152, a regression
+introduced in version 1.5.">
+ <action dev="markt" type="fix" issue="POOL-152" due-to="Bushov Alexander">
+ GenericObjectPool can block forever in borrowObject when the pool is exhausted and a newly created
+ object fails validation. When borrowing an object if a new object is created but validate fails,
+ the latch should not be returned to the queue as an exception will be thrown.
+ </action>
+ </release>
+ <release version="1.5.3" date="2009-09-21" description=
+"This is a patch release containing a fix for POOL-149, a regression
+introduced in version 1.5.">
+ <action dev="markt" type="fix" issue="POOL-149" due-to="Shuyang Zhou">
+ Fix case where a thread could end up waiting indefinitely even if objects
+ were available. Also fixes a couple of leaks in the internal processing
+ object count that could lead to pool exhaustion.
+ </action>
+ </release>
+ <release version="1.5.2" date="2009-07-12" description=
+"This is a patch release containing fixes for POOL-146 and POOL-147, regressions
+introduced in version 1.5.">
+ <action dev="markt" type="fix" issue="POOL-146">
+ Handle the case where one key has reached maxActive but other keys have not.
+ Prior to the fix for this issue, threads waiting on objects from keyed pools
+ still having instances available could be blocked by a thread requesting an
+ instance from an exhausted pool.
+ </action>
+ <action dev="markt" type="fix" issue="POOL-147" due-to="Giambattista Bloisi">
+ Fix case where a thread could end up waiting indefinitely even if objects
+ were available.
+ </action>
+ <action dev="markt" type="fix" issue="POOL-145">
+ Ensure that the GenericKeyedObjectPool idle object evictor does not visit the
+ same instance more than once per eviction run.
+ </action>
+ </release>
+ <release version="1.5.1" date="2009-06-16" description=
+"This is a patch release containing a fix for POOL-144, a regression introduced
+in version 1.5.">
+ <action dev="markt" type="fix" issue="POOL-144">
+ When exhausted action is set to WHEN_EXHAUSTED_BLOCK, maxwait is positive and
+ client threads time out waiting for idle objects, capacity can be "leaked"
+ from GenericObjectPools and GeneritCkeyedObjectPools.
+ </action>
+ </release>
+ <release version="1.5" date="2009-06-10" description=
+"This is a maintenance release including several important bug fixes. This release
+is source and binary compatible with versions 1.3 and 1.4 of commons pool. In addition
+to resolving some important concurrency-related bugs (POOL-135, POOL-125, POOL-29
+POOL-107) this release implements a fairness algorithm to ensure that threads waiting
+for available object instances from GenericObjectPools and GenericKeyedObjectPools are served
+in request arrival order.">
+ <action dev="markt" type="fix" issue="POOL-139" due-to="Sebastian Bazley">
+ StackKeyedObjectPool.getNumActive() needs to be synchronized.
+ </action>
+ <action dev="markt" type="fix" issue="POOL-137" due-to="Sebastian Bazley">
+ Inconsistent synchronization in GenericObjectPool; constant fields should be final.
+ </action>
+ <action dev="markt" type="fix" issue="POOL-75" due-to="Takayuki Kaneko and Gordon Mohr">
+ GenericObjectPool not FIFO with respect to borrowing threads.
+ </action>
+ <action dev="markt" type="fix" issue="POOL-135">
+ _numActive > _maxActive under load
+ </action>
+ <action dev="markt" type="fix" issue="POOL-125">
+ Insufficient control over concurrent access to pooled objects by Evictor, client threads.
+ </action>
+ <action dev="markt" type="fix" issue="POOL-107">
+ Number of connections created has crossed more than maxActive.
+ </action>
+ <action dev="markt" type="fix" issue="POOL-122">
+ java.util.Timer in EvictionTimer does not recover from OutOfMemoryError in Evictor.
+ </action>
+ <action dev="markt" type="fix" issue="POOL-133">
+ Failed object creation may result in invalid active count in GKOP.
+ </action>
+ </release>
+ <release version="1.4" date="2008-01-15" description=
+"This is a maintenance release including numerous bug fixes. This release
+is source and binary compatible with version 1.3 of commons pool, but
+there are some behavior changes introduced to resolve bugs, remove ambiguity
+or improve robustness. Among these are the change in default behavior of
+GenericObjectPool and GenericKeyedObjectPool from FIFO back to LIFO queues
+(as in 1.2 and earlier). The LIFO/FIFO behavior is now configurable. Some of
+the extra synchronization included in version 1.3 was removed / refactored to
+improve performance. The javadoc has also been made more complete and explicit.
+See the detailed list of changes below for specifics on fixed bugs and behavior
+changes in Commons Pool 1.4. This version of Commons Pool depends only on
+JDK version 1.3 or higher. Classes implementing pools are all intended to be
+threadsafe.">
+ <action dev="sandymac" type="fix">
+ Fixed constructor which was ignoring maxTotal parameter:
+ GenericKeyedObjectPool(KeyedPoolableObjectFactory factory, int maxActive, byte whenExhaustedAction,
+ long maxWait, int maxIdle, int maxTotal, boolean testOnBorrow, boolean testOnReturn,
+ long timeBetweenEvictionRunsMillis, int numTestsPerEvictionRun, long minEvictableIdleTimeMillis,
+ boolean testWhileIdle)
+ </action>
+ <action dev="sandymac" type="fix">
+ Changed StackKeyedObjectPool to discard stalest, not freshest, idle object when maxSleeping is reached.
+ </action>
+ <action dev="psteitz" type="fix" issue="POOL-102" due-to="John Sumsion">
+ Allowed blocked threads in GenericObjectPool borrowObject to be interrupted.
+ </action>
+ <action dev="psteitz" type="fix" issue="POOL-86">
+ Fixes to address idle object eviction and LIFO/FIFO behavior reported
+ in POOL-86. Made LIFO/FIFO behavior configurable for GenericObjectPool and
+ GenericKeyedObjectPool, with default set back to LIFO (reverting to 1.2 behavior).
+ Fixed GOP, GKOP evict method and added tests to ensure objects are visited in
+ oldest-to-youngest order. Changed backing store for GOP, GKOP pools back to Commons
+ Collections CursorableLinkedList (brought this class in, repackaged with package scope).
+ </action>
+ <action dev="psteitz" type="fix" issue="POOL-110" due-to="Alexander Pogrebnyak">
+ Changed the default setting for Config.softMinEvictableIdleTimeMillis to
+ GenericObjectPool.DEFAULT_SOFT_MIN_EVICTABLE_IDLE_TIME_MILLIS (was
+ being incorrectly defaulted to DEFAULT_MIN_EVICTABLE_IDLE_TIME_MILLIS).
+ </action>
+ <action dev="psteitz" type="fix" issue="POOL-97" due-to="Mark Thomas">
+ Added a wrapper for the shared idle object eviction timer for all
+ pools. The wrapper class wraps the Timer and keeps track of how many
+ pools are using it. If no pools are using the timer, it is canceled.
+ This prevents a thread being left running which, in application server
+ environments, can lead to memory leaks and/or prevent applications
+ from shutting down or reloading cleanly.
+ </action>
+ <action dev="psteitz" type="fix" issue="POOL-93"
+ due-to="Mark Thomas">
+ Reduced synchronization in GenericObjectPool, GenericKeyedObjectPool.
+ Factory method activations within synchronized blocks were causing
+ performance problems in DBCP and other applications where factory
+ methods could block. Fixes both POOL-93 and POOL-108.
+ </action>
+ <action dev="psteitz" type="fix" issue="POOL-113">
+ Made _testOnBorrow, _testOnReturn volatile and removed synchronization
+ in associated getters and setters in GenericObjectPool,
+ GenericKeyedObjectPool. Made getNumIdle synchronized in
+ StackKeyedObjectPool.
+ </action>
+ <action dev="psteitz" type="fix" issue="POOL-116">
+ Fixed an error in the GenericKeyedObjectPool constructor that takes
+ a Config instance as a parameter. The minIdle setting in the Config
+ was being ignored by the constructor.
+ </action>
+ <action def="psteitz" type="fix" issue="POOL-117">
+ Made behavior on instance validation failure consistent across pools,
+ eliminating possible infinite loops in StackObjectPool,
+ StackKeyedObjectPool, SoftReferenceObjectPool when factory fails to
+ create valid objects.
+ </action>
+ <action dev="sandymac" type="update">
+ When no factory has been defined, addObject now throws
+ IllegalStateExecption instead of NullPointerException for all pools.
+ </action>
+ <action dev="sandymac" type="update">
+ SoftReferenceObjectPool. Improved the accuracy of getNumIdle by
+ "pruning" references to objects that have been garbage collected.
+ </action>
+ <action dev="sandymac" type="update">
+ GenericObjectPool, GenericKeyedObjectPool, SoftReferenceObjectPool,
+ StackObjectPool. Eliminated IllegalStateExceptions when the following
+ operations are attempted on a closed pool: getNumActive, getNumIdle,
+ returnObject, invalidateObject. In each case, the operation is allowed
+ to proceed, reporting the state of the pool that is being shut down, or
+ destroying objects returning to the closed pool.
+ </action>
+ <action dev="sandymac" type="update">
+ StackObjectPool, SoftReferenceObjectPool, GenericKeyedObjectPool. Allowed
+ borrowObject to continue (either examining additional idle instances or
+ with makeObject) when an exception is encountered activating an idle
+ object instead of propagating the exception to the client. Also made
+ addObject propagate (not swallow) exceptions when passivating newly
+ created instances.
+ </action>
+ <action dev="psteitz" type="update">
+ StackKeyedObjectPool. Added validation check for objects returned
+ from borrowObject.
+ </action>
+ <action dev="sandymac" type="update">
+ BaseObjectPool, BaseKeyedObjectPool. Instead of throwing
+ UnsupportedOperationException, the base class implementations
+ of getNumIdle and getNumActive return negative values. The
+ base implementation of close in BaseObjectPool no longer throws
+ IllegalStateException when invoked on an already closed pool.
+ </action>
+
+ </release>
+
+ <release version="1.3" date="2006-04-06" description="1.x bugfix release">
+ <action type="fix">A large number of bug fixes. See release notes for changes.</action>
+ </release>
+
+ <release version="1.2" date="2004-06-07" description="bugfixes">
+ <action dev="dirkv" type="fix">
+ GenericKeyedObjectPoolFactory Config Constructor is incorrect
+ </action>
+ <action dev="dirkv" type="fix">
+ Not possible to extend GenericObjectPool.returnObject() without affecting addObject()
+ </action>
+ </release>
+
+ <release version="1.1" date="2003-10-20" description="bugfixes">
+ <action type="fix">A lot of corner cases were fixed</action>
+ <action type="fix">Performance improvement by optimizing pool synchronization, the critical code paths were optimized by reducing pool synchronization but we also added more synchronization where needed</action>
+ <action type="fix">New minIdle feature: the minimum number of objects allowed in the pool before the evictor thread (if active) spawns new objects. (Note no objects are created when: numActive + numIdle >= maxActive)</action>
+ <action type="fix">New maxTotal feature: a cap on the total number of instances controlled by a pool. Only for GenericKeyedObjectPool where maxActive is a cap on the number of active instances from the pool (per key).</action>
+ <action type="fix">UML Class and sequence diagrams</action>
+ <action type="fix">See bugzilla for more changes</action>
+ </release>
+
+ <release version="1.0.1" date="2002-08-12">
+ <action type="fix">No change log available.</action>
+ </release>
+
+ <release version="1.0" date="2002-05-04">
+ <action type="add">No change log available.</action>
+ </release>
+ </body>
+</document>
diff --git a/src/main/java/org/apache/commons/pool2/impl/BaseGenericObjectPool.java b/src/main/java/org/apache/commons/pool2/impl/BaseGenericObjectPool.java
index 8efb01f..970a3db 100644
--- a/src/main/java/org/apache/commons/pool2/impl/BaseGenericObjectPool.java
+++ b/src/main/java/org/apache/commons/pool2/impl/BaseGenericObjectPool.java
@@ -1,1413 +1,1411 @@
-/*
- * 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 {@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.
- */
- 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.
- *
- * @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.
- *
- * @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.
- *
- * @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 <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 <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
- * <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
- * <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.
- *
- * @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.
- *
- * @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.
- *
- * @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 <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 <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 <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 <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 <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 <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
- * {@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
- * {@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.
- *
- * @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.
- * <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 <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 <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 {@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 {@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 {@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 {@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 {@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.
- *
- * @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 {@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 {@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.
- *
- * @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.
- *
- * @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.
- */
- public abstract void close();
-
- /**
- * Has this pool instance been closed.
- * @return <code>true</code> when this pool has been closed.
- */
- public final boolean isClosed() {
- return closed;
- }
-
- /**
- * <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 {@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.
- */
- final void assertOpen() throws IllegalStateException {
- if (isClosed()) {
- throw new IllegalStateException("Pool not open");
- }
- }
-
- /**
- * <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) {
- if (null != evictor) {
- EvictionTimer.cancel(evictor, evictorShutdownTimeoutMillis, TimeUnit.MILLISECONDS);
- evictor = null;
- evictionIterator = null;
- }
- if (delay > 0) {
- evictor = new Evictor();
- EvictionTimer.schedule(evictor, delay, delay);
- }
- }
- }
-
- /**
- * Stops the evictor.
- */
- void stopEvitor() {
- 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
- */
- 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 <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 {@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.
- * @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.
- * @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.
- * @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.
- * @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.
- * @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 <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 {@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 {@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 {@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.
- * @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.
- * @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.
- *
- * @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.
- *
- * @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.
- *
- * @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.
- * @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.
- * @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.
- * @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.
- */
- 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
- * <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.
- * @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 {@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.
- */
- @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.
- */
- private class StatsStore {
-
- private final AtomicLong values[];
- private final int size;
- private int index;
-
- /**
- * 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.
- *
- * @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.
- *
- * @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.
- */
- 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.
- * @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.
- * @return the idle object deque
- */
- public Deque<PooledObject<T>> getIdleObjects() {
- return idleObjects;
- }
-
- /** {@inheritDoc} */
- @Override
- public boolean hasNext() {
- return idleObjectIterator.hasNext();
- }
-
- /** {@inheritDoc} */
- @Override
- public PooledObject<T> next() {
- return idleObjectIterator.next();
- }
-
- /** {@inheritDoc} */
- @Override
- public void remove() {
- idleObjectIterator.remove();
- }
-
- }
-
- /**
- * Wrapper for objects under management by the pool.
- *
- * GenericObjectPool and GenericKeyedObjectPool maintain references to all
- * objects under management using maps keyed on the objects. This wrapper
- * class ensures that objects can work as hash keys.
- *
- * @param <T> type of objects in the pool
- */
- static class IdentityWrapper<T> {
- /** Wrapped object */
- private final T instance;
-
- /**
- * 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;
- }
-
- /**
- * @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);
- }
-
-
-}
+/*
+ * 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 {@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.
+ */
+ 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.
+ *
+ * @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.
+ *
+ * @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.
+ *
+ * @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 <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 <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
+ * <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
+ * <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.
+ *
+ * @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.
+ *
+ * @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.
+ *
+ * @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 <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 <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 <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 <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 <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 <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
+ * {@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
+ * {@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.
+ *
+ * @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.
+ * <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 <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 <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 {@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 {@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 {@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 {@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 {@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.
+ *
+ * @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 {@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 {@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.
+ *
+ * @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.
+ *
+ * @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.
+ */
+ public abstract void close();
+
+ /**
+ * Has this pool instance been closed.
+ * @return <code>true</code> when this pool has been closed.
+ */
+ public final boolean isClosed() {
+ return closed;
+ }
+
+ /**
+ * <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 {@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.
+ */
+ final void assertOpen() throws IllegalStateException {
+ if (isClosed()) {
+ throw new IllegalStateException("Pool not open");
+ }
+ }
+
+ /**
+ * <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.
+ */
+ void stopEvitor() {
+ 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
+ */
+ 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 <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 {@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.
+ * @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.
+ * @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.
+ * @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.
+ * @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.
+ * @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 <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 {@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 {@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 {@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.
+ * @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.
+ * @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.
+ *
+ * @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.
+ *
+ * @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.
+ *
+ * @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.
+ * @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.
+ * @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.
+ * @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.
+ */
+ 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
+ * <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.
+ * @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 {@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.
+ */
+ @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.
+ */
+ private class StatsStore {
+
+ private final AtomicLong values[];
+ private final int size;
+ private int index;
+
+ /**
+ * 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.
+ *
+ * @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.
+ *
+ * @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.
+ */
+ 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.
+ * @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.
+ * @return the idle object deque
+ */
+ public Deque<PooledObject<T>> getIdleObjects() {
+ return idleObjects;
+ }
+
+ /** {@inheritDoc} */
+ @Override
+ public boolean hasNext() {
+ return idleObjectIterator.hasNext();
+ }
+
+ /** {@inheritDoc} */
+ @Override
+ public PooledObject<T> next() {
+ return idleObjectIterator.next();
+ }
+
+ /** {@inheritDoc} */
+ @Override
+ public void remove() {
+ idleObjectIterator.remove();
+ }
+
+ }
+
+ /**
+ * Wrapper for objects under management by the pool.
+ *
+ * GenericObjectPool and GenericKeyedObjectPool maintain references to all
+ * objects under management using maps keyed on the objects. This wrapper
+ * class ensures that objects can work as hash keys.
+ *
+ * @param <T> type of objects in the pool
+ */
+ static class IdentityWrapper<T> {
+ /** Wrapped object */
+ private final T instance;
+
+ /**
+ * 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;
+ }
+
+ /**
+ * @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);
+ }
+
+
+}
diff --git a/src/main/java/org/apache/commons/pool2/impl/EvictionTimer.java b/src/main/java/org/apache/commons/pool2/impl/EvictionTimer.java
index 738d53c..86e5b54 100644
--- a/src/main/java/org/apache/commons/pool2/impl/EvictionTimer.java
+++ b/src/main/java/org/apache/commons/pool2/impl/EvictionTimer.java
@@ -1,133 +1,135 @@
-/*
- * 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.security.AccessController;
-import java.security.PrivilegedAction;
-import java.util.TimerTask;
-import java.util.concurrent.ScheduledFuture;
-import java.util.concurrent.ScheduledThreadPoolExecutor;
-import java.util.concurrent.ThreadFactory;
-import java.util.concurrent.TimeUnit;
-
-/**
- * Provides a shared idle object eviction timer for all pools.
- * <p>
- * 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.
- * </p>
- * <p>
- * This class has package scope to prevent its inclusion in the pool public API. The class declaration below should
- * *not* be changed to public.
- * </p>
- * <p>
- * This class is intended to be thread-safe.
- * </p>
- *
- * @since 2.0
- */
-class EvictionTimer {
-
- /** Executor instance */
- private static ScheduledThreadPoolExecutor executor; //@GuardedBy("EvictionTimer.class")
-
- /** Prevent instantiation */
- private EvictionTimer() {
- // Hide the default constructor
- }
-
-
- /**
- * @since 2.4.3
- */
- @Override
- public String toString() {
- final StringBuilder builder = new StringBuilder();
- builder.append("EvictionTimer []");
- return builder.toString();
- }
-
-
- /**
- * Add the specified eviction task to the timer. Tasks that are added with a
- * call to this method *must* call {@link #cancel(TimerTask)} 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
- */
- static synchronized void schedule(
- final BaseGenericObjectPool<?>.Evictor task, final long delay, final long period) {
- if (null == executor) {
- executor = new ScheduledThreadPoolExecutor(1, new EvictorThreadFactory());
- executor.setRemoveOnCancelPolicy(true);
- }
- final ScheduledFuture<?> scheduledFuture =
- executor.scheduleWithFixedDelay(task, delay, period, TimeUnit.MILLISECONDS);
- task.setScheduledFuture(scheduledFuture);
- }
-
- /**
- * Remove the specified eviction task from the timer.
- *
- * @param task 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 != null && executor.getQueue().isEmpty()) {
- executor.shutdown();
- try {
- executor.awaitTermination(timeout, unit);
- } catch (final InterruptedException e) {
- // Swallow
- // Significant API changes would be required to propagate this
- }
- executor.setCorePoolSize(0);
- executor = null;
- }
- }
-
- /**
- * Thread factory that creates a 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");
-
- AccessController.doPrivileged(new PrivilegedAction<Void>() {
- @Override
- public Void run() {
- thread.setContextClassLoader(EvictorThreadFactory.class.getClassLoader());
- return null;
- }
- });
-
- return thread;
- }
- }
-}
+/*
+ * 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.security.AccessController;
+import java.security.PrivilegedAction;
+import java.util.TimerTask;
+import java.util.concurrent.ScheduledFuture;
+import java.util.concurrent.ScheduledThreadPoolExecutor;
+import java.util.concurrent.ThreadFactory;
+import java.util.concurrent.TimeUnit;
+
+/**
+ * Provides a shared idle object eviction timer for all pools.
+ * <p>
+ * 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.
+ * </p>
+ * <p>
+ * This class has package scope to prevent its inclusion in the pool public API. The class declaration below should
+ * *not* be changed to public.
+ * </p>
+ * <p>
+ * This class is intended to be thread-safe.
+ * </p>
+ *
+ * @since 2.0
+ */
+class EvictionTimer {
+
+ /** Executor instance */
+ private static ScheduledThreadPoolExecutor executor; //@GuardedBy("EvictionTimer.class")
+
+ /** Prevent instantiation */
+ private EvictionTimer() {
+ // Hide the default constructor
+ }
+
+
+ /**
+ * @since 2.4.3
+ */
+ @Override
+ public String toString() {
+ final StringBuilder builder = new StringBuilder();
+ builder.append("EvictionTimer []");
+ return builder.toString();
+ }
+
+
+ /**
+ * Add the specified eviction task to the timer. Tasks that are added with a
+ * call to this method *must* call {@link #cancel(TimerTask)} 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
+ */
+ static synchronized void schedule(
+ final BaseGenericObjectPool<?>.Evictor task, final long delay, final long period) {
+ if (null == executor) {
+ executor = new ScheduledThreadPoolExecutor(1, new EvictorThreadFactory());
+ executor.setRemoveOnCancelPolicy(true);
+ }
+ final ScheduledFuture<?> scheduledFuture =
+ executor.scheduleWithFixedDelay(task, delay, period, TimeUnit.MILLISECONDS);
+ task.setScheduledFuture(scheduledFuture);
+ }
+
+ /**
+ * Remove the specified eviction task from the timer.
+ *
+ * @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 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);
+ } catch (final InterruptedException e) {
+ // Swallow
+ // Significant API changes would be required to propagate this
+ }
+ executor.setCorePoolSize(0);
+ executor = null;
+ }
+ }
+
+ /**
+ * Thread factory that creates a 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");
+
+ AccessController.doPrivileged(new PrivilegedAction<Void>() {
+ @Override
+ public Void run() {
+ thread.setContextClassLoader(EvictorThreadFactory.class.getClassLoader());
+ return null;
+ }
+ });
+
+ return thread;
+ }
+ }
+}