JDK-8230501: Class data support for hidden classes
forax at univ-mlv.fr
forax at univ-mlv.fr
Tue Nov 10 21:35:10 UTC 2020
> De: "mandy chung" <mandy.chung at oracle.com>
> À: "Remi Forax" <forax at univ-mlv.fr>
> Cc: "valhalla-dev" <valhalla-dev at openjdk.java.net>
> Envoyé: Mardi 10 Novembre 2020 22:17:04
> Objet: Re: JDK-8230501: Class data support for hidden classes
> Hi Remi,
> This is not intended only for the vector API implementation but rather for
> clients who define hidden classes with more than one live objects as class
> data. Otherwise each client will have to write a similar convenience method
> which also needs to handle the unboxing conversion if the constant is a
> primitive type.
> I see the downside for this convenience method is only for List (recommending to
> use immutable list) which can be extended when we have frozen array.
> Any other issues you see for this convenience method?
I think it's better to use a structured object like a record instead of using a list which requires all objects to have the same type.
> On 11/10/20 12:55 PM, Remi Forax wrote:
>> 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 ) but it can be a helper method inside the
>> vector API implementation and not a public method in java.lang.invoke API.
>>  [
>> ] ----- Mail original -----
>>> De: "mandy chung" [ mailto:mandy.chung at oracle.com | <mandy.chung at oracle.com> ]
>>> À: "valhalla-dev" [ mailto:valhalla-dev at openjdk.java.net |
>>> <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 [
>>> ] .
>>> 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 [
>>> ] 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
>>> and `MethodHandles::classDataAt` bootstrap methods.
>>> With this class data support and hidden classes,
>>> will be deprecated for removal. Existing libraries should replace their
>>> calls to `sun.misc.Unsafe::defineAnonymousClass` with
>>> or `Lookup::defineHiddenClassWithClassData`.
>>> 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
>>> 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
>>> 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.
>>> 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`
>>> is called if the hidden class has not been initialized.
>>> Bootstrap methods for class data of other type such as `Map` can be
>>> 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
>>> `Lookup::hasFullPrivilegeAccess` returns true only if it has private, module
>>> and originl access.
>>> `MethodHandles::privateLookupIn` spec is updated to check if the caller
>>> has private and module access. It does not check for original access so
>>> 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
>>> has private access but not full privilege access. `privateLookupIn` is
>>> 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
>>> will have "/allaccess" suffix as opposed to no suffix to indicate full
>>> privilege access.
More information about the valhalla-dev