Uploaded image for project: 'JDK'
  1. JDK
  2. JDK-8280377

MethodHandleProxies does not correctly invoke default methods with varags

XMLWordPrintable

    • b07
    • generic
    • generic

        A DESCRIPTION OF THE PROBLEM :
        When creating an interface proxy to a MethodHandle using MethodHandleProxies.asInterfaceInstance, default methods using a varargs parameter are not correctly handled.
        Calling such a default method on a MethodHandle proxy will produce an IllegalArgumentException with message "array is not of length X", as the method handles are not correctly combined. Default methods with a regular array as their trailing parameter are not affected.

        The cause of this issue is that MethodHandleProxies.callDefaultMethod does not ensure that the MethodHandle obtained for the default method is not a varargs collector (MethodHandle.isVarargsCollector). If it is, it will try to collect varargs arguments, instead of passing the array on "as is". The vararg argument collection has already happened at this point, because the generated java.lang.reflect.Proxy code has no special handling of varargs, it treats them as regular arrays. The fix is that callDefaultMethod needs to call asFixedArity on the result of findSpecial.


        ---------- BEGIN SOURCE ----------
        package com.example;

        import java.lang.invoke.MethodHandleProxies;
        import java.lang.invoke.MethodHandles;

        import static java.lang.invoke.MethodType.methodType;

        public class Main {

            public interface Interface
            {
                void method(Object... args);
                default void defaultMethod(Object... args) {
                    method(args);
                }
                default void defaultMethod2(Object[] args) {
                    method(args);
                }
            }

            private static void callMeViaMethodHandles(String foo, int bar) {
                System.out.println("foo=" + foo + ", bar=" + bar);
            }

            public static void main(String[] args) throws NoSuchMethodException, IllegalAccessException
            {
                var mh = MethodHandles.lookup().findStatic(
                        Main.class, "callMeViaMethodHandles", methodType(void.class, String.class, int.class)
                );
                mh = mh.asSpreader(Object[].class, mh.type().parameterCount());
                var proxy = MethodHandleProxies.asInterfaceInstance(Interface.class, mh);

                // throws incorrect exception
                proxy.defaultMethod("should be foo", 3);
                
                // works fine
                proxy.defaultMethod2(new Object[] { "should be foo", 3 });
            }
        }
        ---------- END SOURCE ----------

        FREQUENCY : always


              mchung Mandy Chung
              webbuggrp Webbug Group
              Votes:
              0 Vote for this issue
              Watchers:
              6 Start watching this issue

                Created:
                Updated:
                Resolved: