pgjdbc/pgjdbc — pull request #197 by sehrope (2014-10-05 15:36:50+00:00)
Title: Fix Timer thread classloader leak

This patch is an alternative to https://github.com/pgjdbc/pgjdbc/pull/188. It fixes the ClassLoader leak when the driver is repeatedly loaded/unloaded (*e.g. in a containerized environment*).

The PR is split into three commits. The first two don't have any functional changes to the driver, they just rename some variables to clarify their usage and move TimerTask related method calls from Statement to go through the Connection rather than statically against the Driver.

The third commit adds a reference counting SharedTimer with two methods, `getTimer()` and `releaseTimer()`. The former creates a Timer on demand and the latter calls `.cancel()` on the underlying Timer if the reference count goes to zero (*to allow it to be GCed*) before clearing it to null.

One nice side effect of this patch is that if a cancellation task is never scheduled, then no Timer or associated Timer thread is ever created.

I added one basic test that creates two connections, two statements, and issues two cancels to test that only a single Timer is created and subsequently deallocated. It and the the rest of the driver tests run successfully.

I think some additional tests are needed, particularly one that simulates loading/unloading the driver via a custom ClassLoader. It would need to run separately from the rest of the driver unit tests as it'll need to run without the driver on the classpath (*as it'll load it dynamically*). If nobody else gets around to this I'll see if I can write one some time next week.

I'd also like if someone could walk through the Timer allocation/deallocation steps to verify the happens-before and memory semantics of it. Again, all the tests pass but another pair of eyes would be appreciated.