On Dec 5, 2007, at 15:23, Chris Bowditch wrote:

Andreas L Delmelle wrote:
On Nov 27, 2007, at 20:06, Andreas L Delmelle wrote:

Hi Andreas,

<snip/>

I tested on Apple JVM 1.4.2 and 1.5.0 on OS X 10.4. Both single- and multi-threaded.
Heap remains stable here over hundreds of runs.
With multiple concurrent runs, my CPU usage easily reaches 180-190% (2 CPUs)

Just to confirm:
In the meantime, I have also run some tests with the same document on Windows XP SP 2 with different versions of the Sun JVM, running 2 concurrent threads on a Centrino Dual Core.
Classes compiled with 1.4 compatibility.
I managed to reproduce the NPE on Java 1.4.2 and 1.5.0, at random intervals, always between 50 and 250 runs.

Thanks for your perservance. Glad its not me going mad :)

Yeah, I thought you'd appreciate it for this very reason... :-)

Still weird though. Logically, from a Java POV, there is no reason why the NPE could ever occur, or IOW: if the NPE occurs, there would be a problem in the JVM's implementation of WeakReferences or synchronized code-blocks or in the garbage-collection algorithm or the thread-synchronization.

If the NPE occurs at that point, either of the variables 'entry' or 'e' would be null. 'entry' = the WeakReference that is obtained by polling the ReferenceQueue. The code-block in question will not be entered if this is null. Possibility A: If it /becomes/ null, this would mean that the WeakReference /itself/ (not its referent) is removed by the garbage- collector while there obviously exists a strong, local reference to it.

'e' = the WeakReference that is obtained by traversing the hash- bucket, looking for 'entry'. Possibility B: If this is null, this would mean that 'entry' could not be found. So, some other thread already cleaned up the stale entry, which would mean that ReferenceQueue.poll() has returned the same WeakReference for another call in that thread... but the only calls to poll() happen inside code-blocks that are synchronized on the CacheSegment to which the ReferenceQueue belongs. As such, they can never occur at the exact same instant. One always has to wait for the other. Come to think of it, one thing I haven't tried, is declaring the ReferenceQueue as 'volatile', but I somehow doubt this would help much here.

You mentioned that your tests were single-threaded. The cause of the NPE can therefore not be MT-related, which rules out Possibility B, and seems to point towards a quirk in the GC and its treatment of WeakReferences. :/


Anyway, enough ranting done. Just glad it worked out.


Cheers

Andreas

Reply via email to