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