# HG changeset patch # User pliden # Date 1541141902 -3600 # Node ID 71564a544d4ca8a8c9997fe89c872c50a4561590 # Parent 2e280ecec24604e760f500cae85855bd142f09c0 8212184: Incorrect oop ref strength used for referents in FinalReference Reviewed-by: eosterlund, kbarrett diff -r 2e280ecec246 -r 71564a544d4c src/hotspot/share/classfile/javaClasses.hpp --- a/src/hotspot/share/classfile/javaClasses.hpp Fri Nov 02 07:46:00 2018 +0100 +++ b/src/hotspot/share/classfile/javaClasses.hpp Fri Nov 02 07:58:22 2018 +0100 @@ -912,6 +912,7 @@ static inline oop queue(oop ref); static inline void set_queue(oop ref, oop value); static bool is_referent_field(oop obj, ptrdiff_t offset); + static inline bool is_final(oop ref); static inline bool is_phantom(oop ref); }; diff -r 2e280ecec246 -r 71564a544d4c src/hotspot/share/classfile/javaClasses.inline.hpp --- a/src/hotspot/share/classfile/javaClasses.inline.hpp Fri Nov 02 07:46:00 2018 +0100 +++ b/src/hotspot/share/classfile/javaClasses.inline.hpp Fri Nov 02 07:58:22 2018 +0100 @@ -127,6 +127,9 @@ HeapWord* java_lang_ref_Reference::discovered_addr_raw(oop ref) { return ref->obj_field_addr_raw(discovered_offset); } +bool java_lang_ref_Reference::is_final(oop ref) { + return InstanceKlass::cast(ref->klass())->reference_type() == REF_FINAL; +} bool java_lang_ref_Reference::is_phantom(oop ref) { return InstanceKlass::cast(ref->klass())->reference_type() == REF_PHANTOM; } diff -r 2e280ecec246 -r 71564a544d4c src/hotspot/share/gc/shared/accessBarrierSupport.cpp --- a/src/hotspot/share/gc/shared/accessBarrierSupport.cpp Fri Nov 02 07:46:00 2018 +0100 +++ b/src/hotspot/share/gc/shared/accessBarrierSupport.cpp Fri Nov 02 07:58:22 2018 +0100 @@ -28,8 +28,16 @@ #include "oops/access.hpp" DecoratorSet AccessBarrierSupport::resolve_unknown_oop_ref_strength(DecoratorSet decorators, oop base, ptrdiff_t offset) { + // Note that the referent in a FinalReference is technically not strong. + // However, it always behaves like one in practice. The two cases are: + // 1) A mutator calls Reference.get(). However, a mutator can only ever + // see inactive FinalReferences, whose referents really are strong. + // 2) A GC heap walking operation. In this case the GC can see active + // FinalReferences, but the GC always wants to follow the referent + // as if it was strong. DecoratorSet ds = decorators & ~ON_UNKNOWN_OOP_REF; - if (!java_lang_ref_Reference::is_referent_field(base, offset)) { + if (!java_lang_ref_Reference::is_referent_field(base, offset) || + java_lang_ref_Reference::is_final(base)) { ds |= ON_STRONG_OOP_REF; } else if (java_lang_ref_Reference::is_phantom(base)) { ds |= ON_PHANTOM_OOP_REF;