Alex Miller has a really interesting blog post up today. In LBQ + GC = slow, he shows how LinkedBlockingQueue can leave a chain of references from tenured dead objects to live young objects. That sounds really dirty, but it actually means something to Java programmers. Something bad.
The effect here is a subtle interaction between the code and the mostly hidden, yet omnipresent, garbage collector. This interaction just happens to hit a known sore spot for the generational garbage collector. I won't spoil the ending, because I want you to read Alex's piece.
In effect, a one-line change to LinkedBlockingQueue has a dramatic effect on the garbage collector's performance. In fact, because the problem causes more full GC's, you'd be likely to observe this problem in an area completely unconnected with the queue itself. By leaving these refchains worming through multiple generations in the heap, the queue damages a resource needed by every other part of the application.
This is a classic common-mode dependency, and it's very hard to diagnose because it results from hidden and asynchronous coupling.