-
Bug
-
Resolution: Fixed
-
P4
-
8, 11, 12
-
b16
-
generic
-
generic
-
Not verified
Issue | Fix Version | Assignee | Priority | Status | Resolution | Resolved In Build |
---|---|---|---|---|---|---|
JDK-8212685 | 11.0.2 | Aleksey Shipilev | P4 | Resolved | Fixed | b02 |
JDK-8218622 | openjdk8u212 | Aleksey Shipilev | P4 | Resolved | Fixed | b01 |
In ThreadLocalBufferAllocator.getBufferAllocator() there is no guarantee that the SoftReference doesn't get cleared between its construction and its later use of bAllocatorRef.get(). Therefore the method can return null. Calling code (e.g. UTF8Reader.<init>() ) does expects to get non-null though and can crash with NPE.
public static BufferAllocator getBufferAllocator() {
SoftReference<BufferAllocator> bAllocatorRef = tlba.get();
if (bAllocatorRef == null || bAllocatorRef.get() == null) {
bAllocatorRef = new SoftReference<>(new BufferAllocator());
tlba.set(bAllocatorRef);
}
return bAllocatorRef.get(); // <--- returns null, because soft-ref was already cleared
}
This semi-reliably crashes SPECjvm2008 XML tests with Shenandoah and aggressive mode that does back-to-back cycles.
Example fix that keeps return value reachable:
public static BufferAllocator getBufferAllocator() {
BufferAllocator ba = null;
SoftReference<BufferAllocator> bAllocatorRef = tlba.get();
if (bAllocatorRef != null) {
ba = bAllocatorRef.get();
}
if (ba == null) {
ba = new BufferAllocator();
bAllocatorRef = new SoftReference<>(ba);
tlba.set(bAllocatorRef);
}
return ba;
}
public static BufferAllocator getBufferAllocator() {
SoftReference<BufferAllocator> bAllocatorRef = tlba.get();
if (bAllocatorRef == null || bAllocatorRef.get() == null) {
bAllocatorRef = new SoftReference<>(new BufferAllocator());
tlba.set(bAllocatorRef);
}
return bAllocatorRef.get(); // <--- returns null, because soft-ref was already cleared
}
This semi-reliably crashes SPECjvm2008 XML tests with Shenandoah and aggressive mode that does back-to-back cycles.
Example fix that keeps return value reachable:
public static BufferAllocator getBufferAllocator() {
BufferAllocator ba = null;
SoftReference<BufferAllocator> bAllocatorRef = tlba.get();
if (bAllocatorRef != null) {
ba = bAllocatorRef.get();
}
if (ba == null) {
ba = new BufferAllocator();
bAllocatorRef = new SoftReference<>(ba);
tlba.set(bAllocatorRef);
}
return ba;
}
- backported by
-
JDK-8212685 Soft reference reclamation race in com.sun.xml.internal.stream.util.ThreadLocalBufferAllocator
- Resolved
-
JDK-8218622 Soft reference reclamation race in com.sun.xml.internal.stream.util.ThreadLocalBufferAllocator
- Resolved