You are viewing a plain text version of this content. The canonical link for it is here.
Posted to dev@commons.apache.org by Attila Szegedi <sz...@freemail.hu> on 2005/02/08 14:26:00 UTC
[pool] Evictor thread
Hi all,
I've just been through a particularly nasty case of debugging a memory
leak where the evictor thread of GenericObjectPool (as used by DBCP) was
not willing to die and let go of a disposed ClassLoader it held as the
loader of a ProtectionDomain of its inherited SecurityContext. Now, while
GenericObjectPool.close() was being called, the Thread running the Evictor
code didn't observe the change in the _cancelled flag. This is
unfortunately perfectly legal under the Java memory model given that there
is neither a synchronization surrounding reading and writing of the flag,
nor a volatile flag on the _cancelled flag.
So, I'd ask you to fix this by adding the "volatile" flag to the "boolean
_cancelled" field of the
org.apache.commons.pool.impl.GenericObjectPool$Evictor class.
Also, it'd be a big improvement in terms of scalability if the
GenericObjectPool held a reference to the Thread running the Evictor
object, and would interrupt() it on close(), so it doesn't take
"timeBetweenEvictionRunsMillis" after a call to close() before the thread
actually clears up.
(All this might not be visible in a more-or-less statical environment, but
is a problem in a system that frequently reloads classes using new class
loaders which are a subclass of java.security.SecureClassLoader and
therefore "decorate" threads with security contexts that ultimately hold a
reference to the class loader. Few loitering class loaders can quickly
escalate into an OutOfMemoryError.)
Thanks,
Attila
---------------------------------------------------------------------
To unsubscribe, e-mail: commons-dev-unsubscribe@jakarta.apache.org
For additional commands, e-mail: commons-dev-help@jakarta.apache.org
Re: [pool] Evictor thread
Posted by Dirk Verbeeck <di...@pandora.be>.
Hi Attila,
You have made some good points, included you will find a new evictor
implementation with the enhancements you proposed. I didn't want to
use interrupt() so I used a wait/notify technique with synchronized
blocks.
Can you try this version and let me know if it works for you?
Cheers
Dirk
=================================================================
class Evictor implements Runnable {
private boolean _cancelled = false;
private long _delay = 0L;
public Evictor(long delay) {
_delay = delay;
}
synchronized void cancel() {
_cancelled = true;
notifyAll();
}
synchronized boolean isCancelled() {
return _cancelled;
}
private synchronized void sleep() {
if (_delay > 0) {
long now = System.currentTimeMillis();
long wakeup = now + _delay;
while (!isCancelled() && (now < wakeup)) {
try {
wait(wakeup - now);
} catch (InterruptedException e) {
// ignored
}
now = System.currentTimeMillis();
}
}
}
public void run() {
sleep();
while(!isCancelled()) {
try {
evict();
} catch(Exception e) {
// ignored
}
try {
ensureMinIdle();
} catch(Exception e) {
// ignored
}
sleep();
}
synchronized(GenericObjectPool.this) {
if(null != _evictionCursor) {
_evictionCursor.close();
_evictionCursor = null;
}
}
}
}
---------------------------------------------------------------------
To unsubscribe, e-mail: commons-dev-unsubscribe@jakarta.apache.org
For additional commands, e-mail: commons-dev-help@jakarta.apache.org