JDK-8230501: Class data support for hidden classes

Remi Forax forax at univ-mlv.fr
Tue Nov 10 20:55:08 UTC 2020

Hi Mandy,
thanks to working on this.

I don't think that adding classDataAt is a good idea, you can emulate it with classData and it's better to get the list once from the class data instead of doing all the checks for each index of the List like classDataAt does.

I understand that the vector API implementation needs to have several arguments (my own test also needs that [1]) but it can be a helper method inside the vector API implementation and not a public method in java.lang.invoke API.


[1] https://github.com/forax/panama-vector/blob/master/fr.umlv.jruntime/src/main/java/fr/umlv/jruntime/Cell.java#L851  

----- Mail original -----
> De: "mandy chung" <mandy.chung at oracle.com>
> À: "valhalla-dev" <valhalla-dev at openjdk.java.net>
> Envoyé: Mardi 10 Novembre 2020 01:12:23
> Objet: JDK-8230501: Class data support for hidden classes

> I'd like to get the discussion on the proposal APIs for class data
> support for hidden classes before posting PR.
> The patch is in https://github.com/mlchung/jdk/tree/class-data.
> This patch also updates the implementation of lambda meta factory and
> Memory Access API to use class data.  I ran the jdk.incubator.foreign
> microbenchmarks and no performance difference.  I'm running more
> performance testing.
> Specdiff
> http://cr.openjdk.java.net/~mchung/jdk16/webrevs/8230501/specdiff/overview-summary.html
> Summary
> -------
> Provide `Lookup::defineHiddenClassWithClassData` API that allow live objects
> be shared between a hidden class and other classes.  A hidden class can load
> these live objects as dynamically-computed constants via
> `MethodHandles::classData`
> and `MethodHandles::classDataAt` bootstrap methods.
> 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`.
> 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
> -------
> Provide `Lookup::defineHiddenClassWithClassData` API that 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 for the class data of the given lookup's lookup class.
> `MethodHandles::classDataAt(Lookup lookup, String name, Class<?> type,
> int index)`
> is a bootstrap method for the element at the given index in the class data
> of the given lookup's lookup class, if the class data is a `List`.
> The hidden class will be initialized when `classData` or `classDataAt`
> method
> is called if the hidden class has not been initialized.
> Bootstrap methods for class data of other type such as `Map` can be
> considered
> in the future while this version also provides a bootstrap method for
> class data list.
> 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.
> `Lookup::hasFullPrivilegeAccess` returns true only if it has private, module
> and originl access.
> `MethodHandles::privateLookupIn` spec is updated to check if the caller
> lookup
> has private and module access.  It does not check for original access so
> that
> a caller can pass a lookup without original access to a framework for
> deep reflection if desired.  It addition, the resulting Lookup object
> does not have the original access.
> Compatibility Risks
> -------------------
> The Lookup object returned by `MethodHandles::privateLookupIn` does not have
> the original access.  If the caller lookup class and target class is in
> the same
> module, it will return a Lookup object with private and module access but
> no original access. The return Lookup object no longer has full
> privilege access.
> Existing code calling `Lookup::hasFullPrivilegeAccess` on a Lookup object
> returned from `privateLookupIn` is impacted since the resulting Lookup
> object
> has private access but not full privilege access. `privateLookupIn` is
> designed
> for frameworks to teleport to a target class with private access for deep
> reflection.  It is believed that `hasFullPrivilegeAccess` is not popularly
> used (it was introduced in 14) and the compatibility risk is expected to
> be low.
> `Lookup::toString` on the return Lookup object from
> `MethodHandles::privateLookupIn`
> will have "/allaccess" suffix as opposed to no suffix to indicate full
> privilege access.

More information about the valhalla-dev mailing list