ale*_*ail 47 java jvm invokedynamic java-7 methodhandle
我正在研究JDK 1.7的新功能,我无法得到它为MethodHandle设计的内容?我理解(直接)静态方法的调用(以及在这种情况下直接使用Core Reflection API).我也理解(直接)调用虚方法(非静态,非最终)(以及使用需要通过Class层次结构的Core Reflection API obj.getClass().getSuperclass()).非虚方法的调用可以视为前者的特殊情况.
是的,我知道存在重载问题.如果要调用方法,则必须提供确切的签名.您无法以简单的方式检查重载方法.
但是,MethodHandle是什么?Reflection API允许您"查看"对象内部,而无需任何预先假设(如实现接口).您可以出于某种目的检查对象.但是MethodHandle的设计是什么呢?我应该何时何地使用它?
更新:我现在正在阅读这篇http://blog.headius.com/2008/09/first-taste-of-invokedynamic.html文章.根据它,主要目标是简化在JVM上运行的脚本语言的生命,而不是Java语言本身.
更新-2:我读完了上面的链接,从那里引用了一些引文:
JVM将成为构建动态语言的最佳VM,因为它已经是一个动态语言VM.而InvokeDynamic通过向一流的JVM公民推广动态语言,将证明这一点.
使用反射来调用方法效果很好......除了一些问题.必须从特定类型检索方法对象,并且不能以一般方式创建.<...>
...反射调用比直接调用慢很多.多年来,JVM已经非常擅长快速反映调用.现代JVM实际上在幕后生成了一堆代码,以避免处理大量开销的旧JVM.但简单的事实是,通过任意数量的层反射访问总是比直接调用慢,部分原因是完全通用的"调用"方法必须检查并重新检查接收器类型,参数类型,可见性和其他细节,但因为参数必须都是对象(所以原语是对象框),并且必须作为一个数组提供,以涵盖所有可能的arities(所以参数得到数组框).
对于执行少量反射调用的库,性能差异可能无关紧要,特别是如果这些调用主要是为了在内存中动态设置静态结构,可以进行正常调用.但是在动态语言中,每次调用必须使用这些机制,这是一个严重的性能损失.
http://blog.headius.com/2008/09/first-taste-of-invokedynamic.html
因此,对于Java程序员来说,它基本上是无用的.我对吗?从这个角度来看,它只能被视为Core Reflection API的替代方式.
Pet*_*rey 34
它是Java 8的前身,为MethodHandles提供语言支持.您将能够直接引用方法,MethodHandles将支持该方法.
您可以使用MethodHandles做的是咖喱方法,更改参数类型并更改其顺序.
方法句柄可以处理方法和字段.
MethodHandles做的另一个技巧是使用原始直接(而不是通过包装)
MethodHandles可以比使用反射更快,因为JVM中有更多的直接支持,例如它们可以内联.它使用新的invokedynamic指令.
Tom*_*ine 11
java.lang.reflect.Method在内存方面相对缓慢且昂贵.方法句柄应该是一种"轻量级"方法,用于传递指向JVM有机会优化的函数的指针.从JDK8开始,方法句柄的优化程度不高,lambdas最初可能是以类的形式实现的(如内部类).
kit*_*yst 10
将MethodHandle视为一种现代的,更灵活,更安全的反射方式.
它目前处于生命周期的早期阶段 - 但随着时间的推移,有可能被优化成必须比反射更快 - 以至于它可以变得像常规方法调用一样快.
自从我提出这个问题以来已经过去了将近 9 年。\nJDK 14 是最后一个稳定版本,它大量使用了 MethodHandle...\n我创建了有关invokedynamic https://alex-ber.medium 的迷你系列文章.com/explaining-invokedynamic-introduction-part-i-1079de618512。下面,我引用他们的相关部分。
MethodHandle可以被认为是更强大的替代品。MethodHandle 就是这样一个对象,它存储有关方法(构造函数、字段或类似的低级操作)的元数据,例如方法的方法签名的名称等。采用它的一种方法是指向方法(取消引用的方法(构造函数、字段或类似的低级操作))。
\nJava 代码可以创建直接访问该代码可访问的任何方法、构造函数或字段的方法句柄。这是通过名为 MethodHandles.Lookup 的基于功能的反射 API 完成的。例如,可以从 Lookup.findStatic 获取静态方法句柄。还有来自 Core Reflection API 对象的转换方法,例如 Lookup.unreflect。
\n了解 Core Reflection API 和 MethodHandle 的两个关键区别非常重要。
\n使用 MethodHandle 时,访问检查仅在构造时执行一次,使用 Core Reflection API 时,它会在每次调用调用方法时执行(并且每次都会调用安全管理器,从而降低性能)。
\n核心反射API调用方法是常规方法。在 MethodHandle 中,所有 invoke* 变体都是签名多态方法。
\n基本上,访问检查意味着您是否可以访问方法(构造函数、字段或类似的低级操作)。例如,如果方法(构造函数、字段或类似的低级操作)是私有的,则您可以正常调用它(从字段获取值)。
\n与Reflection API相反,JVM可以完全透视MethodHandles并尝试优化它们,因此性能更好。
\n注意:使用MethodHandle您还可以生成实现逻辑。有关详细信息,请参阅Dynamical hashCode implementation. Part V https://alex-ber.medium.com/explaining-invokedynamic-dynamical-hashcode-implementation-part-v-16eb318fcd47。