Hi Roland,
Below are some comments on your questions.
1. a connection is allocated. Then the TSCCM will not be
GCed, because an entry in REFERENCE_TO_CONNECTION_SOURCE
prevents it. The entry references the ConnectionPool,
which is a non-static nested class of the TSCCM, and
therefore implicitly references the TSCCM.
REFERENCE_TO_CONNECTION_SOURCE will only have a reference to a
ConnectionPool if a connection is checked out and hasn't been GCed (is
this what you mean by allocated?). In the case when a connnection is
checked out and still active there will be many direct references to
the pool and connection manager so this shouldn't be an issue.
In the case when a connection is checked out, lost, and then GCed the
reference from the REFERENCE_TO_CONNECTION_SOURCE will eventually be
removed by the ReferenceQueueThread.
2. no connection is allocated. Then the TSCCM is GCed,
we have a unit test for this. But how are the open
connections closed in this scenario? I didn't see a
finalizer that would close them.
Currently there is nothing that closes threads other than shutdown.
Not sure if we'd want to put this in a finalizer or not. In general I
have always avoided using them but perhaps this would be a good use
case.
I have also attached changes to the LostConnWorker that should
alleviate the issue with the GC test case. Once this change is made I
think you'll be able to remove all of the code related to the
ReferenceQueueThread. After that is done the only static code left is
related to ALL_CONNECTION_MANAGERS. Is the plan to keep or remove
this code?
Mike
Index: C:/Documents and Settings/Michael/My Documents/HttpClient/HttpComponents-HttpClient/module-client/src/main/java/org/apache/http/impl/conn/ThreadSafeClientConnManager.java
===================================================================
--- C:/Documents and Settings/Michael/My Documents/HttpClient/HttpComponents-HttpClient/module-client/src/main/java/org/apache/http/impl/conn/ThreadSafeClientConnManager.java (revision 558525)
+++ C:/Documents and Settings/Michael/My Documents/HttpClient/HttpComponents-HttpClient/module-client/src/main/java/org/apache/http/impl/conn/ThreadSafeClientConnManager.java (working copy)
@@ -707,17 +707,12 @@
* Creates a new connection pool.
*/
private ConnectionPool() {
- //@@@ currently must be false, otherwise the TSCCM
- //@@@ will not be garbage collected in the unit test...
- boolean conngc = false; //@@@ check parameters to decide
- if (conngc) {
- refQueue = new ReferenceQueue();
- refWorker = new LostConnWorker(this);
- Thread t = new Thread(refWorker); //@@@ use a thread factory
- t.setDaemon(true);
- t.setName("LostConnWorker/"+ThreadSafeClientConnManager.this);
- t.start();
- }
+ refQueue = new ReferenceQueue();
+ refWorker = new LostConnWorker(this);
+ Thread t = new Thread(refWorker); //@@@ use a thread factory
+ t.setDaemon(true);
+ t.setName("LostConnWorker/"+ThreadSafeClientConnManager.this);
+ t.start();
}
/**
@@ -1217,7 +1212,12 @@
private volatile Thread workerThread;
- private final ConnectionPool connPool;
+ /**
+ * Weak reference to the [EMAIL PROTECTED] ConnectionPool} for which this worker is processing
+ * entries. Must be a weak reference to allow the pool and associated
+ * connection manager to be GCed.
+ */
+ private final WeakReference connPoolRef;
/**
@@ -1227,7 +1227,7 @@
* and in which to reclaim the lost connections
*/
public LostConnWorker(ConnectionPool pool) {
- this.connPool = pool;
+ this.connPoolRef = new WeakReference(pool);
}
@@ -1254,12 +1254,14 @@
this.workerThread = Thread.currentThread();
}
- while (this.workerThread == Thread.currentThread()) {
+ while (this.workerThread == Thread.currentThread() && connPoolRef.get() != null) {
try {
// remove the next reference and process it
- Reference ref = connPool.refQueue.remove();
+ // This code is intentionally obtuse to avoid creating a direct reference
+ // to the ConnectionPool
+ Reference ref = ((ConnectionPool) connPoolRef.get()).refQueue.remove();
if (ref instanceof PoolEntryRef) {
- connPool.handleReference((PoolEntryRef) ref);
+ ((ConnectionPool) connPoolRef.get()).handleReference((PoolEntryRef) ref);
}
} catch (InterruptedException e) {
LOG.debug("LostConnWorker interrupted", e);
@@ -1267,7 +1269,7 @@
}
}
- } // class ReferenceQueueThread
+ } // class LostConnWorker
/**
---------------------------------------------------------------------
To unsubscribe, e-mail: [EMAIL PROTECTED]
For additional commands, e-mail: [EMAIL PROTECTED]