On Jun 3, 2020, at 7:38 PM, Mandy Chung <mandy.ch...@oracle.com> wrote: > > On 6/3/20 6:24 PM, John Rose wrote: >> On Jun 3, 2020, at 5:16 PM, Paul Sandoz <paul.san...@oracle.com >> <mailto:paul.san...@oracle.com>> wrote: >>> >>> if (UNSAFE.shouldBeInitialized(cls)) { >>> UNSAFE.ensureClassInitialized(cls); >>> } >>> >>> Although it seems redundant to perform the check, suggesting it is not >>> needed. >> >> It’s useful (IIRC) in this kind of code: >> >> MethodHandle mh = … something about cls ...; >> if (!UNSAFE.shouldBeInitialized(cls)) >> return mh; >> // Oops, every eventual call to mh needs to do the check: >> return filterArguments(mh, 0, UNSAFE_ensureClassInitialized.bindTo(cls)); >> > > It is useful for method handle machinery. I don't see the need to expose it > as a supported API for java applications/framework. > > Maybe useful for dynamic languages?
Yes, it would be. Since it’s a longer conversation, I suggest making a *non-public* API point on Lookup, isFullyInitialized(Class). Further suggestions: See DirectMethodHandle.ensureInitialized for the use of both Unsafe API points in concert; it has ticklish states involving blocking on the thread doing the initialization. I don’t want to expose that yet. But, factor all uses of those two Unsafe API in DMH.java through the new Lookup API points, a public ensureInitialized (I like that name best; it’s the one adopted internally to java.lang.invoke) and also through a new non-public isFullyInitialized. To avoid access checks use IMPL_LOOKUP. Note the inverted boolean sense. The idea is that if isFullyInitialized returns true, then there’s no point in arranging for future calls to ensureInitialized. If there is true demand for the second API point we can roll it out as public. But there’s a catch: There’s a third initialization state, “being initialized” which a dynamic language will also want to care about. So there’s a need for a third API point of some sort, not covered by the second. Here’s a quick thought about that third API point: As things stand, we are going to allow Lookup.findVirtual to apply to Lookup::ensureInitialized to return a suitable access point, for future use, for anyone to use to “tweak” any given class (modulo access restrictions). Good. We can secretly add an optimization to the particular MH (and no other) so that it uses the same machinery as MH’s returned for static getters and setters and invokers that incorporate an init-barrier. I’m not saying do this now, but maybe file a follow-up bug to add that optimization to the resulting MH for Lookup::ensureInit, if and when we add Lookup::isFullyInitialized. That will give the dynamic language people the same “hooks” we enjoy internally. The workflow would be: static final MethodHandle MH_ensureInit = publicLookup().findVirtual(L…, “ensureInitialized”…); MethodHandle mh = …; Class target = …; if (!lookup().isFullyInitialized(target)) { // we need to tack a “before action” onto mh to trigger inits: MethodHandle before = MH_ensureInit.bindTo(lookup()).bindTo(target); mh = MethodHandles.collectArguments(mh, 0, before); } return mh; — John