Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

MethodHandle example throws WrongMethodTypeException on invokeExact call

The example shown in the description of the MethodHandle class throws a WrongMethodTypeException in the invocation of the statement 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 MethodHandle object mh has a symbolic type descriptor corresponding to: (CC)Ljava/lang/String. But when we are invoking mh.invokeExact("daddy",'d','n'), the arguments: d and n are passed as an Object array and then they are not matching with the arguments of the type char.

I know that I can resolve the above problem using the invokeWithArguments instead of the invokeExcat or the invoke, but this example was supposed to work as presented in the description of the MethodHandle of Java 7 API. Besides that, the invokeWithArguments has a performance overhead in relation to invoke/invokeExact.

like image 558
Miguel Gamboa Avatar asked Nov 05 '22 08:11

Miguel Gamboa


1 Answers

How are you compiling this?

It sounds suspiciously like a known Eclipse bug to me.

I've 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();
        }
}

seems to work OK:

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

The relevant portion of output from javap seems sane as well:

  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      
like image 58
kittylyst Avatar answered Nov 09 '22 14:11

kittylyst