Follow

Keep Up to Date with the Most Important News

By pressing the Subscribe button, you confirm that you have read and are agreeing to our Privacy Policy and Terms of Use
Contact

Java MethodHandlers.lookup().findStatic throws NoSuchMethodException

So i have been doing some things that involve Java MethodHandlers. And the reflection api has been around for a long time so there is a lot of documentation about it.

MethodHandlers on the other hand hasn’t been around as long so there is a lot fewer examples. What im trying to do is to invoke a static void function that mutates a state using the MethodHandlers Api.

Here is a runnable example that demonstrates my problem:

MEDevel.com: Open-source for Healthcare and Education

Collecting and validating open-source software for healthcare, education, enterprise, development, medical imaging, medical records, and digital pathology.

Visit Medevel

class Main {
    public static void main(String[] args) throws Throwable {

        System.out.println("Times before: " + Foobar.getTimes());
        final Class<?> aClass = MethodHandles.lookup().findClass(Foobar.class.getName());

        incReflectionApi(aClass);
        incMethodHandler(aClass);

    }

    private static void incReflectionApi(Class<?> aClass) throws Throwable {
        final Method init = aClass.getMethod("increment", (Class<?>[]) null);
        init.invoke(null, (Object[]) null);

        System.out.println("Reflection api: " + Foobar.getTimes());
    }

    private static void incMethodHandler(Class<?> aClass) throws Throwable {

        // Here is where we throw
        final MethodHandle handle = MethodHandles.lookup().findStatic(aClass, "increment", MethodType.methodType(Void.class));
        handle.invoke();

        System.out.println("MethodHandler api: " + Foobar.getTimes());
    }

    public static class Foobar {

        private static int times;

        public static void increment() {
            times++;
        }

        public static int getTimes() {
            return times;
        }
    }
}

So basically, access the increment function and invoke it. Doing so with reflective api getMethod works fine. But when i try to use MethodHandler.lookup#findStatic i get a NoSuchMethodException.

Here is the output of the example:

Times before: 0
Reflection api: 1
Exception in thread "main" java.lang.NoSuchMethodException: no such method: Main$Foobar.increment()Void/invokeStatic
    at java.base/java.lang.invoke.MemberName.makeAccessException(MemberName.java:963)
    at java.base/java.lang.invoke.MemberName$Factory.resolveOrFail(MemberName.java:1101)
    at java.base/java.lang.invoke.MethodHandles$Lookup.resolveOrFail(MethodHandles.java:2030)
    at java.base/java.lang.invoke.MethodHandles$Lookup.findStatic(MethodHandles.java:1102)
    at Main.incMethodHandler(scratch_5.java:26)
    at Main.main(scratch_5.java:14)
Caused by: java.lang.NoSuchMethodError: 'java.lang.Void Main$Foobar.increment()'
    at java.base/java.lang.invoke.MethodHandleNatives.resolve(Native Method)
    at java.base/java.lang.invoke.MemberName$Factory.resolve(MemberName.java:1070)
    at java.base/java.lang.invoke.MemberName$Factory.resolveOrFail(MemberName.java:1098)
    ... 4 more

Am i missing something obvious?

>Solution :

You specified Void.class for the expected return type which represents the wrapper type Void rather than the primitive void.

Here’s a tweaked example:

class Main {
    public static void main(String[] args) throws Throwable {
        System.out.println("Times before: " + Foobar.getTimes());
        final Class<?> aClass = Foobar.class;

        incReflectionApi(aClass);
        incUnreflect(aClass);
        incMethodHandle(aClass);
    }

    private static void incReflectionApi(Class<?> aClass) throws Throwable {
        final Method init = aClass.getMethod("increment");
        init.invoke(null);

        System.out.println("Reflection api: " + Foobar.getTimes());
    }

    private static void incUnreflect(Class<?> aClass) throws Throwable {
        final Method init = aClass.getMethod("increment");
        init.invoke(null);

        final MethodHandle handle = MethodHandles.lookup().unreflect(init);
        handle.invokeExact();

        System.out.println("Reflection to MH: " + Foobar.getTimes());
    }

    private static void incMethodHandle(Class<?> aClass) throws Throwable {
        final MethodHandle handle = MethodHandles.lookup()
            .findStatic(aClass, "increment", MethodType.methodType(void.class));
        handle.invokeExact();

        System.out.println("MethodHandle api: " + Foobar.getTimes());
    }

    public static class Foobar {
        private static int times;

        public static void increment() {
            times++;
        }

        public static int getTimes() {
            return times;
        }
    }
}
Add a comment

Leave a Reply

Keep Up to Date with the Most Important News

By pressing the Subscribe button, you confirm that you have read and are agreeing to our Privacy Policy and Terms of Use

Discover more from Dev solutions

Subscribe now to keep reading and get access to the full archive.

Continue reading