- html - 出于某种原因,IE8 对我的 Sass 文件中继承的 html5 CSS 不友好?
- JMeter 在响应断言中使用 span 标签的问题
- html - 在 :hover and :active? 上具有不同效果的 CSS 动画
- html - 相对于居中的 html 内容固定的 CSS 重复背景?
请提供一段用一些众所周知的动态语言(例如 JavaScript)编写的代码,以及该代码在使用 invokedynamic 的 Java 字节码中的样子,并解释为什么使用 invokedynamic 是向前迈出的一步。
我已经在 Google 上搜索并阅读了很多关于不再是新的 invokedynamic 指令的信息,互联网上的每个人都同意它有助于加速 JVM 上的动态语言。 Thanks to stackoverflow我设法让我自己的字节码指令与 Sable/Jasmin 一起运行。
我知道 invokedynamic 对惰性常量很有用,我也认为我理解了 the OpenJDK takes advantage of invokedynamic for lambdas .
Oracle 有 a small example ,但据我所知,在这种情况下,invokedynamic 的使用违背了目的,因为“加法器”的示例可能更简单、更快,并且与以下字节码表达的效果大致相同:
aload whereeverAIs
checkcast java/lang/Integer
aload whereeverBIs
checkcast java/lang/Integer
invokestatic IntegerOps/adder(Ljava/lang/Integer;Ljava/lang/Integer;)Ljava/lang/Integer;
因为出于某种原因,Oracle 的引导方法知道两个参数都是整数。他们甚至“承认”:
[..]it assumes that the arguments [..] will be Integer objects. A bootstrap method requires additional code to properly link invokedynamic [..] if the parameters of the bootstrap method (in this example, callerClass, dynMethodName, and dynMethodType) vary.
嗯,是的,如果没有那个有趣的“附加代码”,那么在这里使用 invokedynamic 是没有意义的,是吗?
因此,在那之后以及一些其他的 Javadoc 和博客条目之后,我认为我已经很好地掌握了如何在 invokestatic/invokevirtual/invokevirtual 或 getfield 也能正常工作时使用 invokedynamic 作为糟糕的替代品。
现在我很好奇如何将 invokedynamic 指令实际应用到现实世界的用例中,以便它实际上是对“传统”调用的一些改进(除了惰性常量,我得到了那些......)。
最佳答案
实际上,如果您广义地理解“延迟创建”一词,那么延迟操作就是 invokedynamic
的主要优势。例如,Java 8 的 lambda 创建特性是一种惰性创建,其中包括可能包含最终将由 invokedynamic
指令调用的代码的实际类在执行该指令。
这可以转换到所有类型的脚本语言,以不同于 Java 字节码的形式提供代码(甚至可能在源代码中)。在这里,代码可以在第一次调用方法之前编译并在之后保持链接。但是,如果脚本语言支持重新定义方法,它甚至可能会变得未链接。这使用了 invokedynamic
的第二个重要特性,允许可变的 CallSite
之后可以更改,同时在不重新定义的情况下频繁调用时支持最大性能。
这种事后更改 invokedynamic
目标的可能性允许另一个选项,在第一次调用时链接到解释执行,计算执行次数并仅在超过阈值后编译代码(并重新链接到然后编译代码)。
关于基于运行时实例的动态方法分派(dispatch),很明显invokedynamic
不能省略分派(dispatch)算法。但是,如果您在运行时检测到特定调用站点将始终调用相同具体类型的方法,您可以将 CallSite
重新链接到优化代码,该代码将简短检查目标是否符合预期然后键入并执行优化操作,但仅在测试失败时才分支到执行完整动态调度的通用代码。如果它检测到快速路径检查失败了一定次数,该实现甚至可能取消优化这样的调用站点。
这类似于 invokevirtual
和 invokeinterface
如何在 JVM 内部进行优化.因此,使用 invokedynamic
您可以将相同的技术用于任意查找算法。
但如果您想要一个完全不同的用例,您可以使用 invokedynamic
来实现标准访问修饰符规则不支持的 friend
语义。假设你有一个类 A
和 B
意味着有这样的 friend
关系,因为 A
是允许的调用 B
的 private
方法。然后,所有这些调用都可以编码为具有所需名称和签名的 invokedynamic
指令,并指向 B
中的 public
引导方法,可能看起来像这个:
public static CallSite bootStrap(Lookup l, String name, MethodType type)
throws NoSuchMethodException, IllegalAccessException {
if(l.lookupClass()!=A.class || (l.lookupModes()&0xf)!=0xf)
throw new SecurityException("unprivileged caller");
l=MethodHandles.lookup();
return new ConstantCallSite(l.findStatic(B.class, name, type));
}
它首先验证提供的 Lookup
对象是否具有对 A
的完全访问权限,因为只有 A
能够构造这样的对象。因此,错误来电者的偷偷摸摸的尝试在这个地方被整理出来。然后它使用对 B
具有完全访问权限的 Lookup
对象来完成链接。所以,这些 invokedynamic
指令中的每一个在第一次调用后都永久链接到 B
的匹配 private
方法,以与普通相同的速度运行之后调用。
关于dynamic - invokedynamic 什么时候真正有用(除了惰性常量)?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/24171950/
我先说我正在学习 Haskel,所以不要太苛刻。 Haskell 的惰性求值可能有用也可能危险,这取决于计算的瓶颈是时间复杂度还是堆栈的大小。 出于这个原因,我想更好地了解 Haskell 中求值的工
我正在开发一款玩具 RTS 游戏,我依赖 A* 寻找路径,问题是很多单位四处移动导致计算的路径变得无效,这导致 CPU 周期浪费,我必须为那些重新计算路径代理商。 所以我想为什么不懒惰地计算路径而不是
我正在尝试非贪婪地解析出 TD 标签。我从这样的事情开始: stuffMore stuffOther stuffthingsmore things 我使用以下作为我的正则表达式: Regex.Spli
我正在学习 http://learnyouahaskell.com/starting-out 上的(优秀的)Haskell 教程。并且正在尝试直角三角形示例: > let triangles = [(
我编写了一个小型 Haskell 程序来打印当前目录中所有文件的 MD5 校验和(递归搜索)。基本上是 md5deep 的 Haskell 版本.一切都很好,除非当前目录有大量文件,在这种情况下我会收
我通常听说生产代码应该避免使用惰性 I/O。我的问题是,为什么?除了闲逛之外,还可以使用 Lazy I/O 吗?是什么让替代方案(例如枚举器)更好? 最佳答案 惰性 IO 存在的问题是,释放您所获取的
我注意到 Scala 提供了lazy vals。但我不明白他们在做什么。 scala> val x = 15 x: Int = 15 scala> lazy val y = 13 y: Int =
我目前正在尝试将 XML 文件的内容读入 Map Int (Map Int String) 并且它工作得很好(使用 HaXml)。但是,我对程序的内存消耗不满意,问题似乎出在垃圾回收上。 这是我用来读
lazy val seq: Unit = { println("a") seq } 我们可以尾递归调用上面的表达式吗? 最佳答案 我想你可以从这个意义上说,是的 - 评估时,seq将递归评估自
在以下示例中: def maybeTwice2(b: Boolean, i: => Int) = { lazy val j = i if (b) j+j else 0 } 为什么当我这样调用它
我的一个项目使用了混合的Scala功能,这些功能似乎不能很好地融合在一起: 类型类和无形自动类型类实例派生 隐式转换(向具有类型类实例的类型添加有用的语法) 默认参数,因为即使它们通常是一件坏事,但在
我有一个应用程序,涉及一个数组集合,这些数组可能非常大(索引最大为 int 的最大值),但它们是惰性 - 它们内容是动态计算的,并且在请求之前实际上是不知道的。数组也是不可变的 - 每个数组的每个元素
最近我开始使用 spring 中的惰性初始化功能很多。所以我一直在徘徊——懒惰地初始化你的 bean 有什么实际的缺点吗?如果不是 - 为什么不是懒惰的默认行为? 最佳答案 主要的“缺点”是不能立即发
我有一个通过信息亭向访问者显示的网站。人们可以与之互动。但是,由于该网站不是本地托管的,而是使用互联网连接 - 页面加载速度很慢。 我想实现某种惰性缓存机制,以便在人们浏览页面时 - 页面和页面引用的
我是否正确理解声明关系急切加载的方法是使用lazy='joined'或lazy='subquery'? “lazy”与“eager”相反——在这种情况下使用“lazy”关键字来表示急切加载,这是一个历
我想抓取 对之间任何值的内容标签。 This is one block of text This is another one 我想出的正则表达式是 /(.*)/m 虽然,它看起来很贪心,并
考虑以下几点: z = [{"x" => 5}, 2, 3].lazy.map{ |i| i} #=> #5}, 2, 3]>:map> z.first #=> {"x"=>5} 当我尝试将 z 转换
因此我有一个条件语句: if($boolean && expensiveOperation()){ ...} PHP 是否具有惰性 bool 值评估,即它是否会检查 $boolean 并且如果它为 f
我在 Scala 上有问题。我用 @transient lazy val 序列化了一个类的实例 field 。然后我反序列化它,该字段被分配null .我期待反序列化后的惰性评估。我该怎么办? 以下是
我编写了以下函数,我认为该函数应该以原子方式执行 IO(只要其他人都使用相同的 MVar)。 atomicIO :: MVar () -> IO a -> IO a atomicIO mvar io
我是一名优秀的程序员,十分优秀!