问题 关于Java-7中的签名多态方法


据我所知,随着Java 7中MethodHandle的引入,引入了编译器生成的方法重载。

MethodHandle的javadoc 各州(我已经修剪过这些例子):

以下是一些用法示例:

Object x, y; String s; int i;
mh = ...
// (Ljava/lang/String;CC)Ljava/lang/String;
// (String, char, char) -> String
s = (String) mh.invokeExact("daddy",'d','n');

// (Ljava/lang/Object;Ljava/lang/Object;Ljava/lang/Object;)Ljava/lang/Object;
// (Object, Object, Object) -> Object
x = mh.invokeExact((Object)1, (Object)2, (Object)3);

// (Ljava/util/List;)I
// (List) -> int
i = (int) mh.invokeExact(java.util.Arrays.asList(1,2,3));

// (Ljava/io/PrintStream;Ljava/lang/String;)V
// (PrintStream, String) -> void
mh.invokeExact(System.out, "Hello, world.");

上述每个调用都会生成一个invokevirtual指令   使用名称invoke和类型描述符指示   注释。参数类型直接取自实际   参数,而返回类型是立即从演员表中获取的   适用于通话。这个演员可能是一个原始人。如果是   缺少,如果在上下文中发生调用,则类型默认为Object   它使用返回值。如果调用作为语句,强制转换发生   是不可能的,没有回归类型;电话无效。

实际上,invokeExact和friends的行为就好像每个可能的参数组合和返回类型都有重载。

我听说MethodHandles正在为Java 8中的功能做准备,比如lambdas。 (我知道它们对脚本语言已经很有用了。)

[/介绍]

那么,是否有更多这些编译器生成的重载隐藏在Java中?是否有提示将来会有更多这些提示(例如,使用扩展方法)?为什么首先需要它?仅速度?它如何帮助lambdas(我以为lambdas会编译成一个匿名的内部类)?

简而言之,理由是什么;为什么他们(生成的重载)现在和将来都有用?

UPDATE:我的意思 编译器生成的 在这里,Oracle员工称之为超载 签名多态性


12239
2017-12-20 18:34


起源



答案:


我刚刚遇到了Hotspot internals wiki MethodHandles和invokedynamic

它提出了一些有趣的观点来回答这些问题(以及其他一些问题)。

  • 什么叫做 编译器生成的重载 在这个问题上,java家伙打来电话 签名多态。
  • MethodHandle.invokeExact 和朋友 很独特 是唯一的签名多态方法。
  • 在HotSpot VM上, invokevirtual MethodHandle.invoke *的字节码被秘密转换为 invokehandle 指令。
    • invokehandle 就好像 invokedynamic;一些内部结构是不同的,每个都是不同的 invokedynamic 指令必须指向它自己的常量池缓存条目(CPCE), invokehandles可以分享CPCE。
  • invokedynamic 使用非公开的 MethodHandle.invokeBasic 在HotSpot VM上
    • MethodHandle.invokeBasic 就像invokeExact但更松散;例如,它不会检查呼叫站点的类型与被叫方的类型。
  • 热方法句柄(包括 invokedynamic) 可 JIT编译

另外, lambda表达式 将会 通过实施 invokedynamic。 (来自Edwin Dalorzo的回答。)这意味着lambda表达式

  • 将间接使用 MethodHandle.invokeBasic 在HotSpot VM上(见上文),和
  • 有资格成为JIT编译者

12
2017-12-22 06:17



+1很棒的参考资料。 - Edwin Dalorzo


答案:


我刚刚遇到了Hotspot internals wiki MethodHandles和invokedynamic

它提出了一些有趣的观点来回答这些问题(以及其他一些问题)。

  • 什么叫做 编译器生成的重载 在这个问题上,java家伙打来电话 签名多态。
  • MethodHandle.invokeExact 和朋友 很独特 是唯一的签名多态方法。
  • 在HotSpot VM上, invokevirtual MethodHandle.invoke *的字节码被秘密转换为 invokehandle 指令。
    • invokehandle 就好像 invokedynamic;一些内部结构是不同的,每个都是不同的 invokedynamic 指令必须指向它自己的常量池缓存条目(CPCE), invokehandles可以分享CPCE。
  • invokedynamic 使用非公开的 MethodHandle.invokeBasic 在HotSpot VM上
    • MethodHandle.invokeBasic 就像invokeExact但更松散;例如,它不会检查呼叫站点的类型与被叫方的类型。
  • 热方法句柄(包括 invokedynamic) 可 JIT编译

另外, lambda表达式 将会 通过实施 invokedynamic。 (来自Edwin Dalorzo的回答。)这意味着lambda表达式

  • 将间接使用 MethodHandle.invokeBasic 在HotSpot VM上(见上文),和
  • 有资格成为JIT编译者

12
2017-12-22 06:17



+1很棒的参考资料。 - Edwin Dalorzo


这两个链接可能无法回答您的所有问题,但它们可能是一个很好的起点:

这是来自目前在JDK 8:Lambda项目中工作的专家组的参考资料。幸运的是,你可以在那里找到一些解释,首先是关于你对lambda表达式作为内部类的错误概念。


4
2017-12-21 12:26



非常翔实。谢谢! - Michael Deardeuff