On Fri, 23 Oct 2020 20:41:31 GMT, Paul Sandoz <psan...@openjdk.org> wrote:
>> Jorn Vernee has updated the pull request incrementally with one additional >> commit since the last revision: >> >> Make internalName helper method static > > This approach does not work for reference types, since they are erased to > `Object`, and then exact checking will be performed on the erased reference > types. > > For example try this: > > import java.lang.invoke.MethodHandles; > import java.lang.invoke.VarHandle; > > public class Test { > int x; > > public static void main(String[] args) throws Throwable { > VarHandle x = MethodHandles.lookup().findVarHandle(Test.class, "x", > int.class); > VarHandle ex = x.asExact(); > Test t = new Test(); > ex.set(t, 1); > } > } > > Which results in: > > Exception in thread "main" java.lang.invoke.WrongMethodTypeException: > expected (Object,int)void but found (Test,int)void > at Test.main(Test.java:11) > > Exact type checking requires that match be performed on the VH access mode > method type and the exact symbolic method type, something like: > > final static Object guard_L_L(VarHandle handle, Object arg0, > VarHandle.AccessDescriptor ad) throws Throwable { > if (handle.vform.exact && handle.accessModeType(ad.type) != > ad.symbolicMethodTypeExact) { > throw new WrongMethodTypeException("expected " + > handle.vform.methodType_table_exact[ad.type] + " but found " > + ad.symbolicMethodTypeExact); > } > > Then it's precisely the same as `MH.invokeExact`, rather than `MH.invoke`. > > A `VarForm` is a resource shared across many instances of the same _kind_ of > `VarHandle`, so cannot be used for exact matching, except in specific > scenarios e.g. access on a primitive array. @PaulSandoz Thanks. I initially tested this with memory access VarHandles, which don't erase the receiver type. e.g. MemoryLayout layout = MemoryLayout.ofSequence(10, JAVA_INT); VarHandle vh = layout.varHandle(int.class, MemoryLayout.PathElement.sequenceElement()); vh = vh.asExact(); try (MemorySegment segment = MemorySegment.allocateNative(layout)) { for (int i = 0; i <10; i++) { vh.set(segment.baseAddress(), i, i); } } Will result in: Exception in thread "main" java.lang.invoke.WrongMethodTypeException: expected (MemoryAddress,long,int)void but found (MemoryAddress,int,int)void at java.base/java.lang.invoke.VarHandleGuards.guard_LII_V(VarHandleGuards.java:915) at main.Main.main(Main.java:18) Which led me to believe the approach would work for other reference types. But, I suppose the MethodTypes fed to memaccess VarForms are non-erased as an exception rather than a rule. I'll update the patch and sharpen the tests to check that the actual expected type is correct (per the exception message). ------------- PR: https://git.openjdk.java.net/jdk/pull/843