如何识别反编译的 Scala 代码中的装箱/拆箱?
在对这个问题的公认最佳回答中,有一个明确的解释为什么会发生拳击。
但是,如果我反编译代码(使用 java 反编译器),我看不到 scala.runtime.BoxesRunTime 的使用。此外,如果我分析代码(使用 JProfiler),我看不到 BoxesRunTime 的任何实例。
那么,我如何真正看到装箱/拆箱发生的证据呢?
In the accepted best response to this question, there is a clear explanation why boxing happens.
However, if I decompile the code (using java decompiler) I cannot see use of scala.runtime.BoxesRunTime. Furthermore, if I profile the code (using JProfiler) I cannot see any instances of BoxesRunTime.
So, how do I really see a proof of boxing/unboxing taking place?
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(2)
在此代码中:
调用
bar
应首先对整数进行装箱。使用 Scala 2.8.1 进行编译并使用:查看为
Main
类的main
方法生成的字节码:您可以看到对
BoxesRunTime 在调用
bar
之前。BoxesRunTime
是一个包含原始类型装箱方法的对象,因此总共应该有一个实例。这里的技巧是库中的这个特定文件是用 Java 编写的,并且转换是静态方法。因此,尽管在 Scala 代码中使用它感觉就像是一个对象,但在运行时没有任何它的实例。您可能应该使用 JProfile 查找装箱原语(例如 java.lang.Integer),尽管我不确定 JVM 是如何工作的以及它是否实际上可以在运行时重写代码并对其进行优化以避免装箱。据我所知,它不应该应用专业化(但我相信 CLR 可以)。有或没有装箱情况的一些微基准测试是了解运行时发生情况的另一种方法。
编辑:
上面假设类型参数未使用
@specialized
注释进行注释。在这种情况下,可以避免装箱/拆箱。标准库中的某些类是专门的。请参阅此 sid。In this code:
The invocation of
bar
should first box the integer. Compiling with Scala 2.8.1 and using:to see the bytecode produced for the
main
method of theMain
class yields:You can see the call to
BoxesRunTime
before the call tobar
.BoxesRunTime
is an object which contains boxing methods for primitive types, so there should be exactly one instance in total. The trick here is that this particular file in the library was written in Java, and the conversions are static methods. For this reason there aren't any instances of it at runtime, although using it in Scala code feels as if it were an object.You should probably look for boxed primitives (e.g. java.lang.Integer) with JProfile, though I am uncertain how the JVM works and whether it may actually rewrite the code at runtime and optimize it to avoid boxing. To my knowledge, it shouldn't apply specialization (but I believe CLR does). A few microbenchmarks with and without the boxing situation are another way to figure out what happens at runtime.
EDIT:
The above is assuming that a type parameter wasn't annotated with the
@specialized
annotation. In this case, the boxing/unboxing can be avoided. Certain classes in the standard library are specialized. See this sid.给定以下 Test.scala 程序:
如果我使用 scalac -Xprint:jvm Test.scala 进行编译,我会得到此片段,表明发生了专门化(抱歉粘贴得很宽):
可能就是您不这样做的原因查看字节码中任何装箱的证据...
Given the following Test.scala program:
If I compile with
scalac -Xprint:jvm Test.scala
, I get this snippet suggesting that specialization occurs (sorry for wide paste):Could be why you don't see any evidence of boxing in bytecode...