RFR: JDK-8227831: Avoid using volatile for write-once, read-many class field
Kazunori Ogata
OGATAK at jp.ibm.com
Fri Jul 19 05:35:25 UTC 2019
Hi Mandy,
Thank you for your reply. I measured your patch, and the performance was
about 4% better than mine. Since it is faster and cleaner, I agree your
patch looks better.
Regards,
Ogata
"core-libs-dev" <core-libs-dev-bounces at openjdk.java.net> wrote on
2019/07/19 02:58:50:
> From: Mandy Chung <mandy.chung at oracle.com>
> To: Claes Redestad <claes.redestad at oracle.com>, David Holmes
> <david.holmes at oracle.com>
> Cc: core-libs-dev at openjdk.java.net
> Date: 2019/07/19 02:59
> Subject: [EXTERNAL] Re: RFR: JDK-8227831: Avoid using volatile for
write-
> once, read-many class field
> Sent by: "core-libs-dev" <core-libs-dev-bounces at openjdk.java.net>
>
> JDK-8219774 is relevant to this patch (this was discussed in the code
> review for JDK-8219378: NPE in ReflectionFactory.newMethodAccessor
> when langReflectAccess not initialized).
>
> This cleans up the initialization of LangReflectAccess:
> http://cr.openjdk.java.net/~mchung/jdk14/8219774/webrev.00/
>
> I moved LangReflectAccess to jdk.internal.access to be consistent with
> other *Access classes (LangReflectAccess was added before the common
> SharedSecrets class was introduced). AccessibleObject was initialized
> early during startup and this patch causes initializing SharedSecret and
> LangReflectAccess earlier. This is not an official review for
JDK-8219774
> but I'm interested if this improves the performance comparing with
> Ogata's patch.
>
> Ogato - can you help running the micro benchmark you have with
> the patch for JDK-8219774?
>
> thanks
> Mandy
>
> On 7/18/19 2:53 AM, Claes Redestad wrote:
> > Hi David,
> >
> > On 2019-07-18 06:26, David Holmes wrote:
> >> Hi Claes,
> >>
> >> On 18/07/2019 1:04 am, Claes Redestad wrote:
> >>> Hi,
> >>>
> >>> removing volatile aligns LangReflectAccess initialization with the
> >>> pattern used for other access objects: it's only initialized in the
> >>> static initializer of some class which we ensure is initialized,
which
> >>> means any initialization race is guarded by the initialization of
said
> >>> class - in this case j.l.r.Modifier.
> >>
> >> If the field is not volatile then we are not guaranteed to correctly
> >> see the constructed LangReflectAccess instance. Without volatile (or
> >> without additional use of unconditional sync in the accessor) we do
> >> not have a happens-before relationship between the construction of
> >> the LRA instance, and the setting of the field >
> >>> Initialization of other access objects are not guarded by any
> >>> explicit synchronization, however, since similar load/store barriers
> >>> will be in effect by ensuring the class that constructs the object
has
> >>> been initialized. So I think you could remove the explicit
> >>> synchronization.
> >>
> >> We are not guaranteed to hit the class initialization checks that
> >> would guarantee the necessary ordering.
> >
> > You better not look at the existing code in
> > jdk.internal.access.SharedSecrets :-)
> >
> > Would the unsafe.ensureClassInitialized(..) pattern used there bring
> > stronger guarantees? That would be the pattern I'm suggesting the code
> > under review here to align with.
> >
> > And for the record none of the *Access objects carry state and are
> > strictly delegating to either static methods/constructors or instance
> > methods on their arguments.
> >
> > /Claes
> >
> >>
> >> David
> >> -----
> >>
> >>> I'm not sure why LangReflectAccess has not moved in with other
> >>> SharedSecrets. Perhaps this is just an artefact of having been
around
> >>> for a long time, but maybe that'd cause some cyclic bootstrap
> >>> dependency. Either way it's nice to see it align to use the same
> >>> pattern.
> >>>
> >>> Thanks!
> >>> /Claes
> >>>
> >>> On 2019-07-17 10:00, Kazunori Ogata wrote:
> >>>> Hi Aleskey,
> >>>>
> >>>> Thank you for your comment.
> >>>>
> >>>> I forgot to mention one thing. I verified that all accesses to
> >>>> langReflectioAccess calls the accessor "langReflectAccess()".
> >>>> Since this
> >>>> variable is modified once from null to non-null, I think the write
> >>>> in the
> >>>> setter is guaranteed to be visible in the getter by putting the
> >>>> synchronized block in langReflectAccess().
> >>>>
> >>>> Should I put comments about this assumption? Actually, in JDK11
> >>>> there are
> >>>> some lines that do not call the getter, so backport needs to fix
them,
> >>>> too.
> >>>>
> >>>>
> >>>> Regards,
> >>>> Ogata
> >>>>
> >>>>
> >>>> Aleksey Shipilev <shade at redhat.com> wrote on 2019/07/17 16:49:08:
> >>>>
> >>>>> From: Aleksey Shipilev <shade at redhat.com>
> >>>>> To: Kazunori Ogata <OGATAK at jp.ibm.com>,
> >>>>> core-libs-dev at openjdk.java.net
> >>>>> Date: 2019/07/17 16:49
> >>>>> Subject: [EXTERNAL] Re: RFR: JDK-8227831: Avoid using volatile for
> >>>> write-
> >>>>> once, read-many class field
> >>>>>
> >>>>> On 7/17/19 8:48 AM, Kazunori Ogata wrote:
> >>>>>> Webrev: http://cr.openjdk.java.net/~ogatak/8227831/webrev/
> >>>>>
> >>>>> Note this is generally not safe: it introduces data race on
> >>>>> langReflectAccess field access. It has
> >>>>> to be proved that everything that implements LangReflectAccess
> >>>>> interface
> >>>>
> >>>>> makes this data race
> >>>>> benign: e.g. all fields that are accessed via those implementation
> >>>>> are
> >>>>> final, read once, etc. And
> >>>>> briefly looking at that, I am not sure it is the case for the
actual
> >>>>> accessor generators.
> >>>>>
> >>>>> I'd cautiously leave "volatile" here.
> >>>>>
> >>>>> --
> >>>>> Thanks,
> >>>>> -Aleksey
> >>>>>
> >>>>> [attachment "signature.asc" deleted by Kazunori Ogata/Japan/IBM]
> >>>>
>
>
More information about the core-libs-dev
mailing list