Re: RFR: 8230501: Class data support for hidden classes [v4]
On Mon, 23 Nov 2020 17:48:31 GMT, Mandy Chung wrote: > > It is my understanding that `Lookup` object returned from > > defineHiddenClass[WithClassData] features the ORIGINAL access lookup mode, > > right? I cannot find a normative statement to confirm this. If it is the > > case, then it would be good to clarify this. > > Yes with ORIGINAL access. I updated `@return` for both `defineHiddenClass` > and `defineHiddenClassWithClassData` as follows: > > ``` > - * @return the {@code Lookup} object on the hidden class > + * @return the {@code Lookup} object on the hidden class with > + * {@linkplain #ORIGINAL original} and > + * {@linkplain Lookup#hasFullPrivilegeAccess() full privilege} access > ``` Thank you. This addresses my concern. - PR: https://git.openjdk.java.net/jdk/pull/1171
Re: RFR: 8230501: Class data support for hidden classes [v4]
On Mon, 23 Nov 2020 10:23:25 GMT, Chris Hegarty wrote: > It is my understanding that `Lookup` object returned from > defineHiddenClass[WithClassData] features the ORIGINAL access lookup mode, > right? I cannot find a normative statement to confirm this. If it is the > case, then it would be good to clarify this. Yes with ORIGINAL access. I updated `@return` for both `defineHiddenClass` and `defineHiddenClassWithClassData` as follows: - * @return the {@code Lookup} object on the hidden class + * @return the {@code Lookup} object on the hidden class with + * {@linkplain #ORIGINAL original} and + * {@linkplain Lookup#hasFullPrivilegeAccess() full privilege} access - PR: https://git.openjdk.java.net/jdk/pull/1171
Re: RFR: 8230501: Class data support for hidden classes [v4]
On Thu, 19 Nov 2020 11:08:26 GMT, Jorn Vernee wrote: >> Mandy Chung has updated the pull request incrementally with one additional >> commit since the last revision: >> >> Fix the name passed to condy calling classData > > Left 2 minor comments on the new additions in line. It is my understanding that `Lookup` object returned from defineHiddenClass[WithClassData] features the ORIGINAL access lookup mode, right? I cannot find a normative statement to confirm this. If it is the case, then it would be good to clarify this. - PR: https://git.openjdk.java.net/jdk/pull/1171
Re: RFR: 8230501: Class data support for hidden classes [v4]
On Fri, 20 Nov 2020 20:23:27 GMT, Mandy Chung wrote: >> src/java.base/share/classes/java/lang/invoke/MethodHandles.java line 2148: >> >>> 2146: * (unlike private static fields that are accessible to >>> nestmates). >>> 2147: * Care should be taken w.r.t. mutability for example when >>> passing >>> 2148: * an array or other mutable structure through the class data. >> >> I don't think it's necessarily clear _why_/_how_ care should be taken from >> this text. I suggest: >> Suggestion: >> >> * Care should be taken w.r.t. mutability for example when passing >> * an array or other mutable structure through the class data. Such >> * a constant should not be mutated, as downstream consumers of >> * this constant, such as other constants, are not guaranteed to see >> * the updated value, depending on the timing of their resolution. > > What about: > > --- a/src/java.base/share/classes/java/lang/invoke/MethodHandles.java > +++ b/src/java.base/share/classes/java/lang/invoke/MethodHandles.java > @@ -2156,8 +2156,10 @@ public class MethodHandles { > * (unlike private static fields that are accessible to nestmates). > * Care should be taken w.r.t. mutability for example when passing > * an array or other mutable structure through the class data. > - * If you use a {@code List}, it is a good practice to make it > unmodifiable > - * for example via {@link List#of List::of}. > + * Changing any value stored at the class data at runtime may lead to > + * unpredictable behavior. > + * If the class data is a {@code List}, it is a good practice to > make it > + * unmodifiable for example via {@link List#of List::of}. > * > * @param bytes the class bytes > * @param classData pre-initialized class data Looks good! - PR: https://git.openjdk.java.net/jdk/pull/1171
Re: RFR: 8230501: Class data support for hidden classes [v4]
On Thu, 19 Nov 2020 10:59:30 GMT, Jorn Vernee wrote: >> Mandy Chung has updated the pull request incrementally with one additional >> commit since the last revision: >> >> Fix the name passed to condy calling classData > > src/java.base/share/classes/java/lang/invoke/MethodHandles.java line 2148: > >> 2146: * (unlike private static fields that are accessible to >> nestmates). >> 2147: * Care should be taken w.r.t. mutability for example when >> passing >> 2148: * an array or other mutable structure through the class data. > > I don't think it's necessarily clear _why_/_how_ care should be taken from > this text. I suggest: > Suggestion: > > * Care should be taken w.r.t. mutability for example when passing > * an array or other mutable structure through the class data. Such > * a constant should not be mutated, as downstream consumers of > * this constant, such as other constants, are not guaranteed to see > * the updated value, depending on the timing of their resolution. What about: --- a/src/java.base/share/classes/java/lang/invoke/MethodHandles.java +++ b/src/java.base/share/classes/java/lang/invoke/MethodHandles.java @@ -2156,8 +2156,10 @@ public class MethodHandles { * (unlike private static fields that are accessible to nestmates). * Care should be taken w.r.t. mutability for example when passing * an array or other mutable structure through the class data. - * If you use a {@code List}, it is a good practice to make it unmodifiable - * for example via {@link List#of List::of}. + * Changing any value stored at the class data at runtime may lead to + * unpredictable behavior. + * If the class data is a {@code List}, it is a good practice to make it + * unmodifiable for example via {@link List#of List::of}. * * @param bytes the class bytes * @param classData pre-initialized class data - PR: https://git.openjdk.java.net/jdk/pull/1171
Re: RFR: 8230501: Class data support for hidden classes [v4]
On Wed, 18 Nov 2020 00:50:22 GMT, Mandy Chung 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)` and >> `MethodHandles::classDataAt(Lookup lookup, String name, Class type, int >> index)` >> are the bootstrap methods 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. >> >> 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 or
Re: RFR: 8230501: Class data support for hidden classes [v4]
On Wed, 18 Nov 2020 17:26:02 GMT, Paul Sandoz wrote: >> Mandy Chung has updated the pull request incrementally with one additional >> commit since the last revision: >> >> Fix the name passed to condy calling classData > > IIUC `classData` can be used for an original lookup that is not produced by > the result of `defineHiddenClassWithClassData`, but in such cases the class > data will always be null. > > Since `defineHiddenClassWithClassData` rejects null values for class data, we > could detect such usage and throw in the bootstrap methods. That would > require a special constant assignment for hidden classes with no class data. > Probably not worth it. > > Recommend an API note. @PaulSandoz @JornVernee can you please review CSR: https://bugs.openjdk.java.net/browse/JDK-8256214 - PR: https://git.openjdk.java.net/jdk/pull/1171
Re: RFR: 8230501: Class data support for hidden classes [v4]
On Wed, 18 Nov 2020 17:26:02 GMT, Paul Sandoz wrote: > IIUC classData can be used for an original lookup that is not produced by the > result of defineHiddenClassWithClassData, but in such cases the class data > will always be null. Yes that's the case. I see some clarification would help.I added the following in the spec of `classData` and `classDataAt`: * A hidden class created by {@link Lookup#defineHiddenClass(byte[], boolean, Lookup.ClassOption...) * Lookup::defineHiddenClass} and non-hidden classes have no class data. * {@code null} is returned if this method is called on the lookup object * on these classes. - PR: https://git.openjdk.java.net/jdk/pull/1171
Re: RFR: 8230501: Class data support for hidden classes [v4]
On Wed, 18 Nov 2020 16:51:47 GMT, Paul Sandoz wrote: >> Mandy Chung has updated the pull request incrementally with one additional >> commit since the last revision: >> >> Fix the name passed to condy calling classData > > src/java.base/share/classes/java/lang/invoke/MethodHandles.java line 342: > >> 340: } catch (ClassCastException e) { >> 341: throw e; >> 342: } catch (Throwable e) { > > The following might be more appropriate so, in general, errors and runtime > exceptions are not explicitly wrapped: > > try { > return BootstrapMethodInvoker.widenAndCast(classdata, type); > } > catch (RuntimeException | Error e) { > throw e; > } > catch (Throwable e) { > throw new InternalError("Unexpected exception", e); > } > > same applies to `classDataAt` and `ConstantBootstraps.explicitCast`. > Refinement of the runtime exceptions is also possible, but i think the key > thing here is to let errors pass through and any possibly expected runtime > exceptions will get wrapped in `BootstrapMethodError`. Yes a good refinement. diff --git a/src/java.base/share/classes/java/lang/invoke/ConstantBootstraps.java b/src/java.base/share/classes/java/lang/invoke/ConstantBootstraps.java index 71cae83e160..27d74284dc6 100644 --- a/src/java.base/share/classes/java/lang/invoke/ConstantBootstraps.java +++ b/src/java.base/share/classes/java/lang/invoke/ConstantBootstraps.java @@ -413,8 +413,8 @@ public final class ConstantBootstraps { MethodHandle conv = MethodHandles.explicitCastArguments(id, mt); try { return conv.invoke(value); -} catch (ClassCastException e) { -throw e; // specified, let CCE through +} catch (RuntimeException|Error e) { +throw e; // let specified CCE and other runtime exceptions/errors through } catch (Throwable throwable) { throw new InternalError(throwable); // Not specified, throw InternalError } diff --git a/src/java.base/share/classes/java/lang/invoke/MethodHandles.java b/src/java.base/share/classes/java/lang/invoke/MethodHandles.java index cd9bdbaf5a3..368948ab5a8 100644 --- a/src/java.base/share/classes/java/lang/invoke/MethodHandles.java +++ b/src/java.base/share/classes/java/lang/invoke/MethodHandles.java @@ -337,8 +342,8 @@ public class MethodHandles { try { return BootstrapMethodInvoker.widenAndCast(classdata, type); - } catch (ClassCastException e) { - throw e; + } catch (RuntimeException|Error e) { + throw e; // let CCE and other runtime exceptions through } catch (Throwable e) { throw new InternalError(e); } @@ -409,8 +414,8 @@ public class MethodHandles { try { Object element = classdata.get(index); return BootstrapMethodInvoker.widenAndCast(element, type); -} catch (ClassCastException|NullPointerException|IndexOutOfBoundsException e) { -throw e; +} catch (RuntimeException|Error e) { +throw e; // let specified exceptions and other runtime exceptions/errors through } catch (Throwable e) { throw new InternalError(e); } > test/jdk/java/lang/invoke/MethodHandles/classData/ClassDataTest.java line 77: > >> 75: */ >> 76: @Test >> 77: public void noClassData() throws Throwable { > > `throws Throwable` needed on this and other method declarations? `noClassData` only needs `IllegalACcessException`. `assertClassData` throws Throwable because it unwraps from `InvocationTargetException`. I can take a pass to clean this up further. - PR: https://git.openjdk.java.net/jdk/pull/1171
Re: RFR: 8230501: Class data support for hidden classes [v4]
On Wed, 18 Nov 2020 00:50:22 GMT, Mandy Chung 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)` and >> `MethodHandles::classDataAt(Lookup lookup, String name, Class type, int >> index)` >> are the bootstrap methods 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. >> >> 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 or
Re: RFR: 8230501: Class data support for hidden classes [v4]
> 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 `loo