package main;

import jdk.incubator.foreign.MemoryHandles;

import java.lang.invoke.MethodHandle;
import java.lang.invoke.MethodHandles;
import java.lang.invoke.MethodType;
import java.lang.invoke.VarHandle;

public class VarHandleCombException {

    static final MethodHandle MH_m;
    static final MethodHandle MH_handler;

    static {
        try {
            MH_m = MethodHandles.lookup().findStatic(VarHandleCombException.class, "m",
                    MethodType.methodType(Widget.class, Widget.class));
            MH_handler = MethodHandles.lookup().findStatic(VarHandleCombException.class, "handler",
                    MethodType.methodType(Widget.class, Exception.class));
        } catch (NoSuchMethodException | IllegalAccessException e) {
            throw new RuntimeException(e);
        }
    }

    public static void main(String[] args) throws Throwable {
        MethodHandle mh = MH_m;
        mh = MethodHandles.catchException(mh, Exception.class, MH_handler);

        Widget w = (Widget) mh.invokeExact(new Widget()); // Exception caught: java.lang.Exception

        VarHandle vh_x = MethodHandles.lookup().findVarHandle(Widget.class, "x", int.class);
        // java.lang.IllegalArgumentException: Cannot adapt a var handle with a method handle which throws checked exceptions
        MemoryHandles.filterCoordinates(vh_x, 0, mh);
    }

    public static Widget handler(Exception e) {
        System.out.println("Exception caught: " + e);
        return null;
    }

    public static Widget m(Widget w) throws Exception {
        throw new Exception();
    }

}

class Widget {
    public int x;
}
