MethodHandle 示例在调用 invokeExact 时抛出 WrongMethodTypeException

发布于 2024-12-26 04:58:23 字数 748 浏览 0 评论 0原文

MethodHandle 类描述中显示的示例在调用语句 mh.invokeExact("daddy",'d','n 时抛出 WrongMethodTypeException ') 并具有以下描述:(CC)Ljava/lang/String;不能使用与 ([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 相关。

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.

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(2

剪不断理还乱 2025-01-02 04:58:23

你如何编译这个?

对我来说,这听起来很像一个已知的 Eclipse bug。

我刚刚检查了 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      

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      
傲娇萝莉攻 2025-01-02 04:58:23

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

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

invokeExact requires exact match between the MH's method type description, and the types of arguments. Since the MH's method type is (cc)string, so what you want to execute the MH, both the first and second argument should be char. Thus, it is like that

``String s = (String)mh.invokeExact('a', 'b')``
~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文