RFR: 8254354: Add an asExact() VarHandle combinator [v2]

Paul Sandoz psandoz at openjdk.java.net
Fri Oct 23 20:44:41 UTC 2020


On Fri, 23 Oct 2020 18:06:51 GMT, Jorn Vernee <jvernee at openjdk.org> wrote:

>> Hi,
>> 
>> This patch adds an asExact() combinator to VarHandle, that will return a new VarHandle that performs exact type checks, similar to MethodHandle::invokeExact, to help developers catch inexact VarHandle usage, which can lead to performance degradation.
>> 
>> This is implemented using a boolean flag in VarForm. If the flag is set, the exact type of the invocation is checked against the exact type in the VarForm. If there is a mismatch, a WrongMethodTypeException is thrown.
>> 
>> Other than that, there is also an asGeneric() combinator added that does the inverse operation (thanks to Rémi for the suggestion). I've also added The `@Hidden` annotation to the VarHandleGuards methods, as well as a type-checking helper method called from the generic invocation lambda form, so that the stack trace we get points at the location where the VarHandle is being used.
>> 
>> Thanks,
>> Jorn
>> 
>> GH action link (at time of submission): https://github.com/JornVernee/jdk/actions/runs/324660237
>
> 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.

-------------

PR: https://git.openjdk.java.net/jdk/pull/843


More information about the core-libs-dev mailing list