RFR: 8230501: Class data support for hidden classes

Mandy Chung mchung at openjdk.java.net
Wed Nov 11 19:24:54 UTC 2020


On Wed, 11 Nov 2020 18:52:10 GMT, Mandy Chung <mchung at openjdk.org> wrote:

> Provide the `Lookup::defineHiddenClassWithClassData` API that allows live objects
> be shared between a hidden class and other classes.  A hidden class can load
> these live objects as dynamically-computed constants via this API.
> 
> Specdiff
> http://cr.openjdk.java.net/~mchung/jdk16/webrevs/8230501/specdiff/overview-summary.html
> 
> With this class data support and hidden classes, `sun.misc.Unsafe::defineAnonymousClass`
> will be deprecated for removal.  Existing libraries should replace their
> calls to `sun.misc.Unsafe::defineAnonymousClass` with `Lookup::defineHiddenClass`
> or `Lookup::defineHiddenClassWithClassData`.
> 
> This patch also updates the implementation of lambda meta factory and
> `MemoryAccessVarHandleGenerator` to use class data.   No performance difference
> observed in the jdk.incubator.foreign microbenchmarks.   A side note: 
> `MemoryAccessVarHandleGenerator` is removed in the upcoming integration of 
> JDK-8254162 but it helps validating the class data support.
> 
> Background
> ----------
> 
> This is an enhancement following up JEP 371: Hidden Classes w.r.t.
> "Constant-pool patching" in the "Risks and Assumption" section.
> 
> A VM-anonymous class can be defined with its constant-pool entries already
> resolved to concrete values. This allows critical constants to be shared
> between a VM-anonymous class and the language runtime that defines it, and
> between multiple VM-anonymous classes. For example, a language runtime will
> often have `MethodHandle` objects in its address space that would be useful
> to newly-defined VM-anonymous classes. Instead of the runtime serializing
> the objects to constant-pool entries in VM-anonymous classes and then
> generating bytecode in those classes to laboriously `ldc` the entries,
> the runtime can simply supply `Unsafe::defineAnonymousClass` with references
> to its live objects. The relevant constant-pool entries in the newly-defined
> VM-anonymous class are pre-linked to those objects, improving performance
> and reducing footprint. In addition, this allows VM-anonymous classes to
> refer to each other: Constant-pool entries in a class file are based on names.
> They thus cannot refer to nameless VM-anonymous classes. A language runtime can,
> however, easily track the live Class objects for its VM-anonymous classes and
> supply them to `Unsafe::defineAnonymousClass`, thus pre-linking the new class's
> constant pool entries to other VM-anonymous classes.
> 
> This extends the hidden classes to allow live objects to be injected
> in a hidden class and loaded them via condy.
> 
> Details
> -------
> 
> A new `Lookup::defineHiddenClassWithClassData` API takes additional
> `classData` argument compared to `Lookup::defineHiddenClass`.
> Class data can be method handles, lookup objects, arbitrary user objects
> or collections of all of the above.
> 
> This method behaves as if calling `Lookup::defineHiddenClass` to define
> a hidden class with a private static unnamed field that is initialized
> with `classData` at the first instruction of the class initializer.
> 
> `MethodHandles::classData(Lookup lookup, String name, Class<?> type)`
> is a bootstrap method to load the class data of the given lookup's lookup class.
> The hidden class will be initialized when `classData` method is called if
> the hidden class has not been initialized.
> 
> For a class data containing more than one single element, libraries can
> create their convenience method to load a single live object via condy.
> We can reconsider if such a convenience method is needed in the future.
> 
> Frameworks sometimes want to dynamically create a hidden class (HC) and add it
> it the lookup class nest and have HC to carry secrets hidden from that nest.
> In this case, frameworks should not to use private static finals (in the HCs
> they spin) to hold secrets because a nestmate of HC may obtain access to
> such a private static final and observe the framework's secret.  It should use
> condy.  In addition, we need to differentiate if a lookup object is created from
> the original lookup class or created from teleporting e.g. `Lookup::in`
> and `MethodHandles::privateLookupIn`.
> 
> This proposes to add a new `ORIGINAL` bit that is only set if the lookup
> object is created by `MethodHandles::lookup` or by bootstrap method invocation.
> The operations only apply to a Lookup object with original access are:
>    - create method handles for caller-sensitve methods
>    - obtain class data associated with the lookup class
> 
> No change to `Lookup::hasFullPrivilegeAccess` and `Lookup::toString` which
> ignores the ORIGINAL bit.
> 
> 
> Compatibility Risks
> -------------------
> 
> `Lookup::lookupModes` includes a new `ORIGINAL` bit.  Most lookup operations
> ignore this original bit except creating method handles for caller-sensitive methods
> that expects the lookup from the original lookup class.  Existing code  compares
> the return value of `lookupModes` to be a fixed value may be impacted.   However
> existing client has no need to expect a fixed value of lookup modes.
> The incompatibility risk of this spec change is low.

Hi Remi,

One primary motivation of the class data support is to allow hidden classes to refer each other as they are nameless and cannot be referenced in the constant-pool entries.    I see the benefit of extending class data support to normal classes that can simplify the bytecode generated with fewer CP entries.   I want to keep the scope just as a follow up to JEP 371 Hidden Classes so that we can deprecate `Unsafe::defineAnonymousClass` for removal.   Soon we can remove the VM anonymous and constant pool patching code from HotSpot VM.

-------------

PR: https://git.openjdk.java.net/jdk/pull/1171


More information about the core-libs-dev mailing list