Handle example throws WrongMethodTypeException when invokeExact is called

The example shown in the class description MethodHandle, calls WrongMethodTypeExceptionin a call to the operator mh.invokeExact("daddy",'d','n')with the following description (CC)Ljava/lang/String; cannot be called with a different arity as ([Ljava/lang/Object;)Ljava/lang/Object;.

The object MethodHandle mhhas a handle character type corresponding to: (CC)Ljava/lang/String. But when we call mh.invokeExact("daddy",'d','n'), the arguments are: dand npassed as an array Object, and then they do not match the type arguments char.

I know that I can solve the above problem by using invokeWithArgumentsinstead of invokeExcator invoke, but this example should have worked like the one presented in MethodHandlethe Java 7 API description . It also invokeWithArgumentshas a performance overhead in relation to invoke/ invokeExact.

+5
source share
2 answers

How do you compile this?

Sounds suspiciously like a known Eclipse bug.

I just checked with javac and this code:

import java.lang.invoke.*;

public class ScratchMH {    
        private static ScratchMH instance = null;

        public ScratchMH() {
                super();
        }

        private void run() throws Throwable {
                Object x, y; String s; int i;
                MethodType mt; MethodHandle mh;
                MethodHandles.Lookup lookup = MethodHandles.lookup();

                // mt is (char,char)String
                mt = MethodType.methodType(String.class, char.class, char.class);
                mh = lookup.findVirtual(String.class, "replace", mt);
                s = (String) mh.invokeExact("daddy",'d','n');
                // invokeExact(Ljava/lang/String;CC)Ljava/lang/String;

                System.out.println(s);
        }

        public static void main(String[] args) throws Throwable {
                instance = new ScratchMH();
                instance.run();
        }
}

works fine:

ariel-2:src boxcat$ javac scratch/clj/ScratchMH.java 
ariel-2:src boxcat$ java scratch/clj/ScratchMH
nanny
ariel-2:src boxcat$ 

The relevant part of the output from javap also seems reasonable:

  35: invokevirtual #8                  // Method java/lang/invoke/MethodHandles$Lookup.findVirtual:(Ljava/lang/Class;Ljava/lang/String;Ljava/lang/invoke/MethodType;)Ljava/lang/invoke/MethodHandle;
  38: astore        6
  40: aload         6
  42: ldc           #9                  // String daddy
  44: bipush        100
  46: bipush        110
  48: invokevirtual #10                 // Method java/lang/invoke/MethodHandle.invokeExact:(Ljava/lang/String;CC)Ljava/lang/String;
  51: astore_3      
+2
source

invokeExactAn exact match is required between the description of the type of the MH method and the types of the arguments. Since the type of the MH method is equal (cc)string, so you want to execute MH, both the first and second arguments must be char. So it looks like

``String s = (String)mh.invokeExact('a', 'b')``
0
source

All Articles