I have been reviewing the 1.5.4 and 1.5.x pool code against the 3 issues identified above:
1.) Creating new object for latch is not synchronized, so there is a probability that other thread overrides the latch pair (GenericKeyedObjectPool:1177)
2.) Allocate() method does not care if the latch pair is already assigned in 1.) (~1245).
3.) I guess latch accesses should be synchronized to avoid latch changes between lines.
re 3: I intend to ignore as per my previous comments until such time as it is substantiated with an explanation of how a problem may occur.
re 1: I disagree with the analysis. Setting mayCreate on the latch is performed inside a sync block on the keyed pool. At the same time as mayCreate is set, the latch is removed from the allocation queue. Therefore, another thread cannot provide an object for that latch. Object creation is performed in the borrowObject() method and the latch is a local variable and is therefore only visible to a single thread. I do not see a sequence of events that could result in two threads creating an object for the same latch.
re 2: Same argument as 1.
All the latch getters and setters are synchronized therefore any attempt to read latch attributes will see the latest values even if the write and read are in separate threads.
So far there have been several explanations of how this issue may occur but, as yet, none of them have stood up to scrutiny (assuming my analysis is correct - not always a valid assumption). I wouldn't be surprised if there was a pool bug here somewhere - the code is somewhat complex - but I'm going to need either a test case that demonstrates the issue or an explanation of how the problem occurs before I start changing any code.
There have been a few fixes (although none that look relevant to this issue) since 1.5.4 so it would be good to update to the latest 1.5.x (or 1.6.x if you want generics) and repeat the tests.