History | Log In     View a printable version of the current page.  
Issue Details (XML | Word | Printable)

Key: BP-49
Type: Bug Bug
Status: Open Open
Priority: Minor Minor
Assignee: Unassigned
Reporter: Joachim Sauer
Votes: 0
Watchers: 0
Operations

If you were logged in you would be able to see more operations.
backport175

Nondeterministic NullPointerException when reading annotation

Created: 07/Dec/05 03:32 AM   Updated: 20/Apr/06 11:11 AM
Component/s: reader
Affects Version/s: 1.0
Fix Version/s: 1.1-RC1

Time Tracking:
Original Estimate: 2 hours
Original Estimate - 2 hours
Remaining Estimate: 2 hours
Remaining Estimate - 2 hours
Time Spent: Not Specified
Remaining Estimate - 2 hours

Environment: Reproduced on both Linux (Fedora Core 3 & 4) and Windows (2000 & XP) with Sun JDKs 1.4 and 5.0


 Description  « Hide
We've noticed occasional errors in our system that we were unable to reproduce reliably and couldn't track down easily (because of a unrelated) bug in some Sun code. A coworker has finally found the cause and produced the following analysis:

This method of org.codehaus.backport175.reader.bytecode.AnnotationReader

public static AnnotationReader getReaderFor(final ClassKey classKey) {
final AnnotationReader reader;
Object value = READERS.get(classKey);
if (value == null) {
synchronized (READERS) { reader = new AnnotationReader(classKey); READERS.put(classKey, new WeakReference(reader));//reader strong refs its own key in the weakhahsmap.. }
} else { reader = (AnnotationReader) ((Reference)value).get(); }
return reader;
}

contains an error. The AnnotationReader that is obtained in the line

reader = (AnnotationReader) ((Reference)value).get();

can be null, as the WeakReference content can be nullified by the VM if no other references to the content exist. In practice, this happens very seldom and non-deterministically. But as it sometimes does occur, null is returned in this case, which leads to a NullPointerException where the reader is used (in the Annotations class). A proposed fix is

public static AnnotationReader getReaderFor(final ClassKey classKey) {
AnnotationReader reader;
Object value = READERS.get(classKey);
if (value == null) {
synchronized (READERS) { reader = new AnnotationReader(classKey); READERS.put(classKey, new WeakReference(reader));//reader strong refs its own key in the weakhahsmap.. }
} else {
reader = (AnnotationReader) ((Reference)value).get();
if (reader == null) {//WeakReference content can be null
synchronized (READERS) { reader = new AnnotationReader(classKey); READERS.put(classKey, new WeakReference(reader)); }
}
}
return reader;
}



 All   Comments   Work Log   Change History      Sort Order: Ascending order - Click to sort in descending order
Jonas Boner - 07/Dec/05 09:15 PM
Thanks a lot for the analysis and the fix, I can see the potential problem now.
I will put this into the CVS HEAD and it will be part of the upcoming 1.1 release.

Dilum Ranatunga - 20/Apr/06 11:11 AM
I am also seeing this issue. I think this is a bigger issue than Minor.

Note that the original code, and the suggested fix both have the double-check anti-pattern:
http://www.cs.umd.edu/~pugh/java/memoryModel/DoubleCheckedLocking.html
http://wiki.jboss.org/wiki/Wiki.jsp?page=ThreadSafeCode