Fix Version/s: 16
Compatibility Risk Description:The incompatibility risk of this spec change is low.
A new ORIGINAL bit is added. Most lookup operations ignore this original bit
except creating method handles for caller-sensitive methods that expects
the lookup from the original lookup class. Looking up caller-sensitive methods
is expected to use lookup created by `MethodHandles::lookup` but not
Existing code that 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. A new ORIGINAL bit is added. Most lookup operations ignore this original bit except creating method handles for caller-sensitive methods that expects the lookup from the original lookup class. Looking up caller-sensitive methods is expected to use lookup created by `MethodHandles::lookup` but not `MethodHandles::privateLookupIn`. Existing code that 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.
Interface Kind:Java API
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
This is a follow up enhancement to JEP 371: Hidden Classes as documented 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
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.
Define a new
Lookup::defineHiddenClassWithClassData API that takes
classData argument compared to
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
The hidden class will be initialized when
is called if the hidden class has not been initialized.
See attached specdiff for the spec changes for:
- In java.lang.invoke.MethodHandles.Lookup class:
Lookup::ORIGINALmode and the following methods are updated to reflect this new mode
- java.lang.invoke.MethodHandles class
MethodHandles::classData(Lookup lookup, String name, Class<?> type)static method
MethodHandles::classDataAt(Lookup lookup, String name, Class<?> type, int index)static method
MethodHandles::privateLookupInare updated to reflect the new
Lookup object produced via teleporting will drop
ORIGINAL bit (including
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.