Summary
-------
Provide `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.
`sun.misc.Unsafe::defineAnonymousClass` will be deprecated for removal.
Existing libraries depending on the constant pool patching of VM-anonymous
class should replace their calls to `sun.misc.Unsafe::defineAnonymousClass`
with `Lookup::defineHiddenClassWithClassData`.
Problem
-------
This is a follow up enhancement to JEP 371: Hidden Classes as documented
in the "Risks and Assumption" section:
___Constant-pool patching___
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.
Solution
--------
Define a new `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 to load an element at the specified index from the class data
if it's a list. It's a convenience method to load one element from class data
via condy.
The hidden class will be initialized when `classData` or `classDataAt` method
is called if the hidden class has not been initialized.
Specification
-------------
See attached specdiff for the spec changes for:
1. In java.lang.invoke.MethodHandles.Lookup class:
- New `Lookup::defineHiddenClassWithClassData` method
- New `Lookup::ORIGINAL` mode and the following methods are updated to reflect this new mode
- `Lookup::lookupModes`
- `Lookup::in`
- `Lookup::dropLookupIn`
2. java.lang.invoke.MethodHandles class
- New `MethodHandles::classData(Lookup lookup, String name, Class<?> type)` static method
- New `MethodHandles::classDataAt(Lookup lookup, String name, Class<?> type, int index)` static method
- `MethodHandles::lookup` and `MethodHandles::privateLookupIn` are updated to reflect the new `ORIGINAL` mode
Compatibility Risks
-------------
The `Lookup` object produced via teleporting will drop `ORIGINAL` bit (including `Lookup::in`, `Lookup::dropLookupIn` and `MethodHandles::privateLookupIn`)
A `Lookup` with original access ensures that this lookup is created by the original lookup class and the bootstrap method invoked by the VM. Such a lookup with original access also has private and module access which has the following additional capability:
- create method handles which invoke caller sensitive methods, such as Class.forName
- obtain the class data associated with the lookup class
Prior to the new `ORIGINAL` bit, a `Lookup` returned by `MethodHandles::privateLookupIn` with both private and module access can lookup caller-sensitive methods. The behavior of the `Lookup` returned by `MethodHandles::privateLookupIn` with both private and module access is changed and it will not be able to lookup any caller-sensitive method.
The behavior of a caller-sensitive method is dependent on the lookup context. So a method handle of caller-sensitive methods is bound with the lookup context at creation time and the lookup context is evaluated at runtime instead of the caller at method invocation time. Therefore a lookup object with the original access must be provided; otherwise, `IllegalAccessException` will be thrown. The intent for `MethodHandles::privateLookupIn` is to allow module authors to authorize libraries or frameworks to do deep reflection on private and module-internal members. Existing code should use `MethodHandles::lookup` (its own lookup with original full privilege access) to obtain caller-sensitive methods instead. The compatibility risk of this behavioral change is low because the full privilege access requirement to lookup caller-sensitive methods is prior to Java SE 9 when `privateLookupIn` is introduced.