【问题标题】:MethodHandle example throws WrongMethodTypeException on invokeExact callMethodHandle 示例在 invokeExact 调用上抛出 WrongMethodTypeException
【发布时间】:2012-01-10 12:15:06
【问题描述】:

MethodHandle 类描述中显示的示例在调用 mh.invokeExact("daddy",'d','n') 语句时抛出了 WrongMethodTypeException,描述如下:(CC)Ljava/lang/String; cannot be called with a different arity as ([Ljava/lang/Object;)Ljava/lang/Object;

MethodHandle 对象mh 有一个符号类型描述符,对应于:(CC)Ljava/lang/String。但是当我们调用mh.invokeExact("daddy",'d','n') 时,参数:dn 作为Object 数组传递,然后它们与char 类型的参数不匹配。

我知道我可以使用invokeWithArguments 而不是invokeExcatinvoke 来解决上述问题,但是这个示例应该按照Java 7 API 的MethodHandle 描述中的说明工作.除此之外,invokeWithArguments 相对于invoke/invokeExact 有性能开销。

【问题讨论】:

    标签: java jvm java-7 invokedynamic methodhandle


    【解决方案1】:

    你是如何编译这个的?

    对我来说,这听起来像是一个已知的 Eclipse 错误。

    我刚刚检查了 javac 和这段代码:

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

    似乎工作正常:

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

    javap 输出的相关部分似乎也很正常:

      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      
    

    【讨论】:

    • 在 Linux 上使用 OpenJDK 1.7.0_07 也看到了这个错误,代码为 of this example
    【解决方案2】:

    invokeExact 要求 MH 的方法类型描述和参数类型完全匹配。由于MH的方法类型是(cc)string,所以要执行MH,第一个参数和第二个参数都应该是char。于是,就这样了

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

    【讨论】:

      猜你喜欢
      • 2021-01-14
      • 2015-02-08
      • 2022-12-17
      • 2019-03-28
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多