package org.apache.commons.pool.impl;
import java.util.ArrayList;
import java.util.Collection;
import java.util.Iterator;
import java.util.LinkedList;
import java.util.List;
import java.util.NoSuchElementException;
import java.util.TimerTask;
import org.apache.commons.pool.BaseObjectPool;
import org.apache.commons.pool.ObjectPool;
import org.apache.commons.pool.PoolUtils;
import org.apache.commons.pool.PoolableObjectFactory;
public class GenericObjectPool extends BaseObjectPool
implements ObjectPool
{
public static final byte WHEN_EXHAUSTED_FAIL = 0;
public static final byte WHEN_EXHAUSTED_BLOCK = 1;
public static final byte WHEN_EXHAUSTED_GROW = 2;
public static final int DEFAULT_MAX_IDLE = 8;
public static final int DEFAULT_MIN_IDLE = 0;
public static final int DEFAULT_MAX_ACTIVE = 8;
public static final byte DEFAULT_WHEN_EXHAUSTED_ACTION = 1;
public static final boolean DEFAULT_LIFO = true;
public static final long DEFAULT_MAX_WAIT = -1L;
public static final boolean DEFAULT_TEST_ON_BORROW = false;
public static final boolean DEFAULT_TEST_ON_RETURN = false;
public static final boolean DEFAULT_TEST_WHILE_IDLE = false;
public static final long DEFAULT_TIME_BETWEEN_EVICTION_RUNS_MILLIS = -1L;
public static final int DEFAULT_NUM_TESTS_PER_EVICTION_RUN = 3;
public static final long DEFAULT_MIN_EVICTABLE_IDLE_TIME_MILLIS = 1800000L;
public static final long DEFAULT_SOFT_MIN_EVICTABLE_IDLE_TIME_MILLIS = -1L;
private int _maxIdle = 8;
private int _minIdle = 0;
private int _maxActive = 8;
private long _maxWait = -1L;
private byte _whenExhaustedAction = 1;
private volatile boolean _testOnBorrow = false;
private volatile boolean _testOnReturn = false;
private boolean _testWhileIdle = false;
private long _timeBetweenEvictionRunsMillis = -1L;
private int _numTestsPerEvictionRun = 3;
private long _minEvictableIdleTimeMillis = 1800000L;
private long _softMinEvictableIdleTimeMillis = -1L;
private boolean _lifo = true;
private CursorableLinkedList _pool = null;
private CursorableLinkedList.Cursor _evictionCursor = null;
private PoolableObjectFactory _factory = null;
private int _numActive = 0;
private Evictor _evictor = null;
private int _numInternalProcessing = 0;
private final LinkedList _allocationQueue = new LinkedList();
public GenericObjectPool()
{
this(null, 8, (byte)1, -1L, 8, 0, false, false, -1L, 3, 1800000L, false);
}
public GenericObjectPool(PoolableObjectFactory factory)
{
this(factory, 8, (byte)1, -1L, 8, 0, false, false, -1L, 3, 1800000L, false);
}
public GenericObjectPool(PoolableObjectFactory factory, Config config)
{
this(factory, config.maxActive, config.whenExhaustedAction, config.maxWait, config.maxIdle, config.minIdle, config.testOnBorrow, config.testOnReturn, config.timeBetweenEvictionRunsMillis, config.numTestsPerEvictionRun, config.minEvictableIdleTimeMillis, config.testWhileIdle, config.softMinEvictableIdleTimeMillis, config.lifo);
}
public GenericObjectPool(PoolableObjectFactory factory, int maxActive)
{
this(factory, maxActive, (byte)1, -1L, 8, 0, false, false, -1L, 3, 1800000L, false);
}
public GenericObjectPool(PoolableObjectFactory factory, int maxActive, byte whenExhaustedAction, long maxWait)
{
this(factory, maxActive, whenExhaustedAction, maxWait, 8, 0, false, false, -1L, 3, 1800000L, false);
}
public GenericObjectPool(PoolableObjectFactory factory, int maxActive, byte whenExhaustedAction, long maxWait, boolean testOnBorrow, boolean testOnReturn)
{
this(factory, maxActive, whenExhaustedAction, maxWait, 8, 0, testOnBorrow, testOnReturn, -1L, 3, 1800000L, false);
}
public GenericObjectPool(PoolableObjectFactory factory, int maxActive, byte whenExhaustedAction, long maxWait, int maxIdle)
{
this(factory, maxActive, whenExhaustedAction, maxWait, maxIdle, 0, false, false, -1L, 3, 1800000L, false);
}
public GenericObjectPool(PoolableObjectFactory factory, int maxActive, byte whenExhaustedAction, long maxWait, int maxIdle, boolean testOnBorrow, boolean testOnReturn)
{
this(factory, maxActive, whenExhaustedAction, maxWait, maxIdle, 0, testOnBorrow, testOnReturn, -1L, 3, 1800000L, false);
}
public GenericObjectPool(PoolableObjectFactory factory, int maxActive, byte whenExhaustedAction, long maxWait, int maxIdle, boolean testOnBorrow, boolean testOnReturn, long timeBetweenEvictionRunsMillis, int numTestsPerEvictionRun, long minEvictableIdleTimeMillis, boolean testWhileIdle)
{
this(factory, maxActive, whenExhaustedAction, maxWait, maxIdle, 0, testOnBorrow, testOnReturn, timeBetweenEvictionRunsMillis, numTestsPerEvictionRun, minEvictableIdleTimeMillis, testWhileIdle);
}
public GenericObjectPool(PoolableObjectFactory factory, int maxActive, byte whenExhaustedAction, long maxWait, int maxIdle, int minIdle, boolean testOnBorrow, boolean testOnReturn, long timeBetweenEvictionRunsMillis, int numTestsPerEvictionRun, long minEvictableIdleTimeMillis, boolean testWhileIdle)
{
this(factory, maxActive, whenExhaustedAction, maxWait, maxIdle, minIdle, testOnBorrow, testOnReturn, timeBetweenEvictionRunsMillis, numTestsPerEvictionRun, minEvictableIdleTimeMillis, testWhileIdle, -1L);
}
public GenericObjectPool(PoolableObjectFactory factory, int maxActive, byte whenExhaustedAction, long maxWait, int maxIdle, int minIdle, boolean testOnBorrow, boolean testOnReturn, long timeBetweenEvictionRunsMillis, int numTestsPerEvictionRun, long minEvictableIdleTimeMillis, boolean testWhileIdle, long softMinEvictableIdleTimeMillis)
{
this(factory, maxActive, whenExhaustedAction, maxWait, maxIdle, minIdle, testOnBorrow, testOnReturn, timeBetweenEvictionRunsMillis, numTestsPerEvictionRun, minEvictableIdleTimeMillis, testWhileIdle, softMinEvictableIdleTimeMillis, true);
}
public GenericObjectPool(PoolableObjectFactory factory, int maxActive, byte whenExhaustedAction, long maxWait, int maxIdle, int minIdle, boolean testOnBorrow, boolean testOnReturn, long timeBetweenEvictionRunsMillis, int numTestsPerEvictionRun, long minEvictableIdleTimeMillis, boolean testWhileIdle, long softMinEvictableIdleTimeMillis, boolean lifo)
{
this._factory = factory;
this._maxActive = maxActive;
this._lifo = lifo;
switch (whenExhaustedAction) {
case 0:
case 1:
case 2:
this._whenExhaustedAction = whenExhaustedAction;
break;
default:
throw new IllegalArgumentException("whenExhaustedAction " + whenExhaustedAction + " not recognized.");
}
this._maxWait = maxWait;
this._maxIdle = maxIdle;
this._minIdle = minIdle;
this._testOnBorrow = testOnBorrow;
this._testOnReturn = testOnReturn;
this._timeBetweenEvictionRunsMillis = timeBetweenEvictionRunsMillis;
this._numTestsPerEvictionRun = numTestsPerEvictionRun;
this._minEvictableIdleTimeMillis = minEvictableIdleTimeMillis;
this._softMinEvictableIdleTimeMillis = softMinEvictableIdleTimeMillis;
this._testWhileIdle = testWhileIdle;
this._pool = new CursorableLinkedList();
startEvictor(this._timeBetweenEvictionRunsMillis);
}
public synchronized int getMaxActive()
{
return this._maxActive;
}
public synchronized void setMaxActive(int maxActive)
{
this._maxActive = maxActive;
allocate();
}
public synchronized byte getWhenExhaustedAction()
{
return this._whenExhaustedAction;
}
public synchronized void setWhenExhaustedAction(byte whenExhaustedAction)
{
switch (whenExhaustedAction) {
case 0:
case 1:
case 2:
this._whenExhaustedAction = whenExhaustedAction;
allocate();
break;
default:
throw new IllegalArgumentException("whenExhaustedAction " + whenExhaustedAction + " not recognized.");
}
}
public synchronized long getMaxWait()
{
return this._maxWait;
}
public synchronized void setMaxWait(long maxWait)
{
this._maxWait = maxWait;
allocate();
}
public synchronized int getMaxIdle()
{
return this._maxIdle;
}
public synchronized void setMaxIdle(int maxIdle)
{
this._maxIdle = maxIdle;
allocate();
}
public synchronized void setMinIdle(int minIdle)
{
this._minIdle = minIdle;
allocate();
}
public synchronized int getMinIdle()
{
return this._minIdle;
}
public boolean getTestOnBorrow()
{
return this._testOnBorrow;
}
public void setTestOnBorrow(boolean testOnBorrow)
{
this._testOnBorrow = testOnBorrow;
}
public boolean getTestOnReturn()
{
return this._testOnReturn;
}
public void setTestOnReturn(boolean testOnReturn)
{
this._testOnReturn = testOnReturn;
}
public synchronized long getTimeBetweenEvictionRunsMillis()
{
return this._timeBetweenEvictionRunsMillis;
}
public synchronized void setTimeBetweenEvictionRunsMillis(long timeBetweenEvictionRunsMillis)
{
this._timeBetweenEvictionRunsMillis = timeBetweenEvictionRunsMillis;
startEvictor(this._timeBetweenEvictionRunsMillis);
}
public synchronized int getNumTestsPerEvictionRun()
{
return this._numTestsPerEvictionRun;
}
public synchronized void setNumTestsPerEvictionRun(int numTestsPerEvictionRun)
{
this._numTestsPerEvictionRun = numTestsPerEvictionRun;
}
public synchronized long getMinEvictableIdleTimeMillis()
{
return this._minEvictableIdleTimeMillis;
}
public synchronized void setMinEvictableIdleTimeMillis(long minEvictableIdleTimeMillis)
{
this._minEvictableIdleTimeMillis = minEvictableIdleTimeMillis;
}
public synchronized long getSoftMinEvictableIdleTimeMillis()
{
return this._softMinEvictableIdleTimeMillis;
}
public synchronized void setSoftMinEvictableIdleTimeMillis(long softMinEvictableIdleTimeMillis)
{
this._softMinEvictableIdleTimeMillis = softMinEvictableIdleTimeMillis;
}
public synchronized boolean getTestWhileIdle()
{
return this._testWhileIdle;
}
public synchronized void setTestWhileIdle(boolean testWhileIdle)
{
this._testWhileIdle = testWhileIdle;
}
public synchronized boolean getLifo()
{
return this._lifo;
}
public synchronized void setLifo(boolean lifo)
{
this._lifo = lifo;
}
public synchronized void setConfig(Config conf)
{
setMaxIdle(conf.maxIdle);
setMinIdle(conf.minIdle);
setMaxActive(conf.maxActive);
setMaxWait(conf.maxWait);
setWhenExhaustedAction(conf.whenExhaustedAction);
setTestOnBorrow(conf.testOnBorrow);
setTestOnReturn(conf.testOnReturn);
setTestWhileIdle(conf.testWhileIdle);
setNumTestsPerEvictionRun(conf.numTestsPerEvictionRun);
setMinEvictableIdleTimeMillis(conf.minEvictableIdleTimeMillis);
setTimeBetweenEvictionRunsMillis(conf.timeBetweenEvictionRunsMillis);
setSoftMinEvictableIdleTimeMillis(conf.softMinEvictableIdleTimeMillis);
setLifo(conf.lifo);
allocate();
}
public Object borrowObject()
throws Exception
{
long starttime = System.currentTimeMillis();
Latch latch = new Latch(null);
byte whenExhaustedAction;
long maxWait;
synchronized (this)
{
whenExhaustedAction = this._whenExhaustedAction;
maxWait = this._maxWait;
this._allocationQueue.add(latch);
allocate();
}
while (true)
{
synchronized (this) {
assertOpen();
}
if (latch.getPair() == null)
{
if (!latch.mayCreate())
{
switch (whenExhaustedAction)
{
case 2:
synchronized (this)
{
if ((latch.getPair() == null) && (!latch.mayCreate())) {
this._allocationQueue.remove(latch);
this._numInternalProcessing += 1;
}
}
break;
case 0:
synchronized (this)
{
if ((latch.getPair() == null) && (latch.mayCreate())) {
break label497;
}
this._allocationQueue.remove(latch);
}
throw new NoSuchElementException("Pool exhausted");
case 1:
try {
synchronized (latch)
{
if ((latch.getPair() == null) && (!latch.mayCreate())) {
if (maxWait <= 0L) {
latch.wait();
}
else
{
long elapsed = System.currentTimeMillis() - starttime;
long waitTime = maxWait - elapsed;
if (waitTime > 0L)
{
latch.wait(waitTime);
}
}
}
else break label497;
}
}
catch (InterruptedException e)
{
synchronized (this)
{
if ((latch.getPair() == null) && (!latch.mayCreate()))
{
this._allocationQueue.remove(latch);
}
else break label497;
}
Thread.currentThread().interrupt();
throw e;
}
if ((maxWait <= 0L) || (System.currentTimeMillis() - starttime < maxWait)) continue;
synchronized (this)
{
if ((latch.getPair() == null) && (!latch.mayCreate()))
{
this._allocationQueue.remove(latch);
}
else break label497;
}
throw new NoSuchElementException("Timeout waiting for idle object");
default:
throw new IllegalArgumentException("WhenExhaustedAction property " + whenExhaustedAction + " not recognized.");
}
}
}
else
{
label497: boolean newlyCreated = false;
if (null == latch.getPair()) {
try {
Object obj = this._factory.makeObject();
latch.setPair(new GenericKeyedObjectPool.ObjectTimestampPair(obj));
newlyCreated = true;
} finally {
if (!newlyCreated)
{
synchronized (this) {
this._numInternalProcessing -= 1;
allocate();
}
}
}
}
try
{
this._factory.activateObject(latch.getPair().value);
if ((this._testOnBorrow) && (!this._factory.validateObject(latch.getPair().value)))
{
throw new Exception("ValidateObject failed");
}
synchronized (this) {
this._numInternalProcessing -= 1;
this._numActive += 1;
}
return latch.getPair().value;
}
catch (Throwable e) {
PoolUtils.checkRethrow(e);
try
{
this._factory.destroyObject(latch.getPair().value);
} catch (Throwable e2) {
PoolUtils.checkRethrow(e2);
}
synchronized (this) {
this._numInternalProcessing -= 1;
if (!newlyCreated) {
latch.reset();
this._allocationQueue.add(0, latch);
}
allocate();
}
if (newlyCreated)
throw new NoSuchElementException("Could not create a validated object, cause: " + e.getMessage());
}
}
}
}
private synchronized void allocate()
{
if (isClosed()) return;
while ((!this._pool.isEmpty()) && (!this._allocationQueue.isEmpty())) {
Latch latch = (Latch)this._allocationQueue.removeFirst();
latch.setPair((GenericKeyedObjectPool.ObjectTimestampPair)this._pool.removeFirst());
this._numInternalProcessing += 1;
synchronized (latch) {
latch.notify();
}
}
while ((!this._allocationQueue.isEmpty()) && ((this._maxActive < 0) || (this._numActive + this._numInternalProcessing < this._maxActive))) {
Latch latch = (Latch)this._allocationQueue.removeFirst();
latch.setMayCreate(true);
this._numInternalProcessing += 1;
synchronized (latch) {
latch.notify();
}
}
}
public void invalidateObject(Object obj)
throws Exception
{
try
{
if (this._factory != null)
this._factory.destroyObject(obj);
}
finally {
synchronized (this) {
this._numActive -= 1;
allocate();
}
}
}
public void clear()
{
List toDestroy = new ArrayList();
synchronized (this) {
toDestroy.addAll(this._pool);
this._numInternalProcessing += this._pool._size;
this._pool.clear();
}
destroy(toDestroy, this._factory);
}
private void destroy(Collection c, PoolableObjectFactory factory)
{
for (Iterator it = c.iterator(); it.hasNext(); )
try {
factory.destroyObject(((GenericKeyedObjectPool.ObjectTimestampPair)it.next()).value);
} catch (Exception e) {
}
finally {
synchronized (this) {
this._numInternalProcessing -= 1;
allocate();
}
}
}
public synchronized int getNumActive()
{
return this._numActive;
}
public synchronized int getNumIdle()
{
return this._pool.size();
}
public void returnObject(Object obj)
throws Exception
{
try
{
addObjectToPool(obj, true);
} catch (Exception e) {
if (this._factory != null) {
try {
this._factory.destroyObject(obj);
}
catch (Exception e2)
{
}
synchronized (this) {
this._numActive -= 1;
allocate();
}
}
}
}
private void addObjectToPool(Object obj, boolean decrementNumActive)
throws Exception
{
boolean success = true;
if ((this._testOnReturn) && (!this._factory.validateObject(obj)))
success = false;
else {
this._factory.passivateObject(obj);
}
boolean shouldDestroy = !success;
synchronized (this) {
if (isClosed()) {
shouldDestroy = true;
}
else if ((this._maxIdle >= 0) && (this._pool.size() >= this._maxIdle)) {
shouldDestroy = true;
} else if (success)
{
if (this._lifo)
this._pool.addFirst(new GenericKeyedObjectPool.ObjectTimestampPair(obj));
else {
this._pool.addLast(new GenericKeyedObjectPool.ObjectTimestampPair(obj));
}
if (decrementNumActive) {
this._numActive -= 1;
}
allocate();
}
}
if (shouldDestroy) {
try {
this._factory.destroyObject(obj);
}
catch (Exception e)
{
}
if (decrementNumActive)
synchronized (this) {
this._numActive -= 1;
allocate();
}
}
}
public void close()
throws Exception
{
super.close();
synchronized (this) {
clear();
startEvictor(-1L);
}
}
/** @deprecated */
public void setFactory(PoolableObjectFactory factory)
throws IllegalStateException
{
List toDestroy = new ArrayList();
PoolableObjectFactory oldFactory = this._factory;
synchronized (this) {
assertOpen();
if (0 < getNumActive()) {
throw new IllegalStateException("Objects are already active");
}
toDestroy.addAll(this._pool);
this._numInternalProcessing += this._pool._size;
this._pool.clear();
this._factory = factory;
}
destroy(toDestroy, oldFactory);
}
public void evict()
throws Exception
{
assertOpen();
synchronized (this) {
if (this._pool.isEmpty()) {
return;
}
if (null == this._evictionCursor) {
this._evictionCursor = this._pool.cursor(this._lifo ? this._pool.size() : 0);
}
}
int i = 0; for (int m = getNumTests(); i < m; i++)
{
GenericKeyedObjectPool.ObjectTimestampPair pair;
synchronized (this) {
if (((this._lifo) && (!this._evictionCursor.hasPrevious())) || ((!this._lifo) && (!this._evictionCursor.hasNext())))
{
this._evictionCursor.close();
this._evictionCursor = this._pool.cursor(this._lifo ? this._pool.size() : 0);
}
pair = this._lifo ? (GenericKeyedObjectPool.ObjectTimestampPair)this._evictionCursor.previous() : (GenericKeyedObjectPool.ObjectTimestampPair)this._evictionCursor.next();
this._evictionCursor.remove();
this._numInternalProcessing += 1;
}
boolean removeObject = false;
long idleTimeMilis = System.currentTimeMillis() - pair.tstamp;
if ((getMinEvictableIdleTimeMillis() > 0L) && (idleTimeMilis > getMinEvictableIdleTimeMillis()))
{
removeObject = true;
} else if ((getSoftMinEvictableIdleTimeMillis() > 0L) && (idleTimeMilis > getSoftMinEvictableIdleTimeMillis()) && (getNumIdle() + 1 > getMinIdle()))
{
removeObject = true;
}
if ((getTestWhileIdle()) && (!removeObject)) {
boolean active = false;
try {
this._factory.activateObject(pair.value);
active = true;
} catch (Exception e) {
removeObject = true;
}
if (active) {
if (!this._factory.validateObject(pair.value))
removeObject = true;
else {
try {
this._factory.passivateObject(pair.value);
} catch (Exception e) {
removeObject = true;
}
}
}
}
if (removeObject)
try {
this._factory.destroyObject(pair.value);
}
catch (Exception e)
{
}
synchronized (this) {
if (!removeObject) {
this._evictionCursor.add(pair);
if (this._lifo)
{
this._evictionCursor.previous();
}
}
this._numInternalProcessing -= 1;
}
}
}
private void ensureMinIdle()
throws Exception
{
int objectDeficit = calculateDeficit(false);
for (int j = 0; (j < objectDeficit) && (calculateDeficit(true) > 0); j++)
try {
addObject();
} finally {
synchronized (this) {
this._numInternalProcessing -= 1;
allocate();
}
}
}
private synchronized int calculateDeficit(boolean incrementInternal)
{
int objectDeficit = getMinIdle() - getNumIdle();
if (this._maxActive > 0) {
int growLimit = Math.max(0, getMaxActive() - getNumActive() - getNumIdle() - this._numInternalProcessing);
objectDeficit = Math.min(objectDeficit, growLimit);
}
if ((incrementInternal) && (objectDeficit > 0)) {
this._numInternalProcessing += 1;
}
return objectDeficit;
}
public void addObject()
throws Exception
{
assertOpen();
if (this._factory == null) {
throw new IllegalStateException("Cannot add objects without a factory.");
}
Object obj = this._factory.makeObject();
try {
assertOpen();
addObjectToPool(obj, false);
} catch (IllegalStateException ex) {
try {
this._factory.destroyObject(obj);
}
catch (Exception ex2) {
}
throw ex;
}
}
protected synchronized void startEvictor(long delay)
{
if (null != this._evictor) {
EvictionTimer.cancel(this._evictor);
this._evictor = null;
}
if (delay > 0L) {
this._evictor = new Evictor(null);
EvictionTimer.schedule(this._evictor, delay, delay);
}
}
synchronized String debugInfo()
{
StringBuffer buf = new StringBuffer();
buf.append("Active: ").append(getNumActive()).append("\n");
buf.append("Idle: ").append(getNumIdle()).append("\n");
buf.append("Idle Objects:\n");
Iterator it = this._pool.iterator();
long time = System.currentTimeMillis();
while (it.hasNext()) {
GenericKeyedObjectPool.ObjectTimestampPair pair = (GenericKeyedObjectPool.ObjectTimestampPair)it.next();
buf.append("\t").append(pair.value).append("\t").append(time - pair.tstamp).append("\n");
}
return buf.toString();
}
private int getNumTests()
{
if (this._numTestsPerEvictionRun >= 0) {
return Math.min(this._numTestsPerEvictionRun, this._pool.size());
}
return (int)Math.ceil(this._pool.size() / Math.abs(this._numTestsPerEvictionRun));
}
private static final class Latch
{
private GenericKeyedObjectPool.ObjectTimestampPair _pair;
private boolean _mayCreate = false;
private Latch()
{
}
private synchronized GenericKeyedObjectPool.ObjectTimestampPair getPair() {
return this._pair;
}
private synchronized void setPair(GenericKeyedObjectPool.ObjectTimestampPair pair)
{
this._pair = pair;
}
private synchronized boolean mayCreate()
{
return this._mayCreate;
}
private synchronized void setMayCreate(boolean mayCreate)
{
this._mayCreate = mayCreate;
}
private synchronized void reset()
{
this._pair = null;
this._mayCreate = false;
}
Latch(GenericObjectPool.1 x0)
{
this();
}
}
public static class Config
{
public int maxIdle = 8;
public int minIdle = 0;
public int maxActive = 8;
public long maxWait = -1L;
public byte whenExhaustedAction = 1;
public boolean testOnBorrow = false;
public boolean testOnReturn = false;
public boolean testWhileIdle = false;
public long timeBetweenEvictionRunsMillis = -1L;
public int numTestsPerEvictionRun = 3;
public long minEvictableIdleTimeMillis = 1800000L;
public long softMinEvictableIdleTimeMillis = -1L;
public boolean lifo = true;
}
private class Evictor extends TimerTask
{
private Evictor()
{
}
public void run()
{
try
{
GenericObjectPool.this.evict();
}
catch (Exception e)
{
}
catch (OutOfMemoryError oome) {
oome.printStackTrace(System.err);
}
try {
GenericObjectPool.this.ensureMinIdle();
}
catch (Exception e)
{
}
}
Evictor(GenericObjectPool.1 x1)
{
this();
}
}
}
common-pool连接池GenericObjectPool源代码
最新推荐文章于 2020-11-04 14:36:45 发布