RFR: 8181085: Race condition in method resolution may produce spurious NullPointerException
Andrew Dinn
adinn at redhat.com
Thu May 25 13:57:32 UTC 2017
On 25/05/17 14:30, Andrew Haley wrote:
> On 25/05/17 14:12, Andrew Dinn wrote:
>> The following webrev fixes a race condition that is present in jdk10 and
>> also jdk9 and jdk8. It is caused by a misplaced volatile keyword that
>> faild to ensure correct ordering of writes by the compiler. Reviews welcome.
>
> Can you explain why we don't need a memory fence there?
We do need one and we have one.
The assignments executed in the relevant method in cpCache.cpp (i.e.
ConstantPoolCacheEntry::set_direct_or_vtable_call) are
. . .
set_f1(method());
. . .
set_bytecode_1(invoke_code);
. . .
If you look at the definition of these two methods they are
void set_f1(Metadata* f1) {
Metadata* existing_f1 = (Metadata*)_f1; // read once
assert(existing_f1 == NULL || existing_f1 == f1, "illegal field
change");
_f1 = f1;
}
and
void ConstantPoolCacheEntry::set_bytecode_1(Bytecodes::Code code) {
#ifdef ASSERT
// Read once.
volatile Bytecodes::Code c = bytecode_1();
assert(c == 0 || c == code || code == 0, "update must be consistent");
#endif
// Need to flush pending stores here before bytecode is written.
OrderAccess::release_store_ptr(&_indices, _indices | ((u_char)code <<
bytecode_1_shift));
On x86 the release_store_ptr operation just reduces to an assignment of
volatile field _indices. That alone doesn't stop the compiler
re-ordering it before the assignment of f1. Making both fields volatile
does stop them being re-ordered.
regards,
Andrew Dinn
-----------
Senior Principal Software Engineer
Red Hat UK Ltd
Registered in England and Wales under Company Registration No. 03798903
Directors: Michael Cunningham, Michael ("Mike") O'Neill, Eric Shander
More information about the jdk10-dev
mailing list