gpt4 book ai didi

scala - 如何在 Scala 中发现装箱/拆箱

转载 作者:行者123 更新时间:2023-12-04 04:07:44 30 4
gpt4 key购买 nike

根据最近的即席建议,关于如何让 Scala 通过查看字节码告诉我是否正在进行拳击,我创建了这个类:

class X { def foo(ls : Array[Long]) = ls map (_.toDouble)

查看 foo 的字节码:
public double[] foo(long[]);
Code:
Stack=4, Locals=2, Args_size=2
0: getstatic #11; //Field scala/Predef$.MODULE$:Lscala/Predef$;
3: aload_1
4: invokevirtual #16; //Method scala/Predef$.longArrayOps:([J)Lscala/collection/mutable/ArrayOps;
7: new #18; //class X$$anonfun$foo$1
10: dup
11: aload_0
12: invokespecial #22; //Method X$$anonfun$foo$1."<init>":(LX;)V
15: getstatic #27; //Field scala/Array$.MODULE$:Lscala/Array$;
18: getstatic #32; //Field scala/reflect/Manifest$.MODULE$:Lscala/reflect/Manifest$;
21: invokevirtual #36; //Method scala/reflect/Manifest$.Double:()Lscala/reflect/AnyValManifest;
24: invokevirtual #40; //Method scala/Array$.canBuildFrom:(Lscala/reflect/ClassManifest;)Lscala/collection/generic/CanBuildFrom;
27: invokeinterface #46, 3; //InterfaceMethod scala/collection/TraversableLike.map:(Lscala/Function1;Lscala/collection/generic/CanBuildFrom;)Ljava/lan g/Object;
32: checkcast #48; //class "[D"
35: areturn
LineNumberTable:
line 7: 0

那里没有装箱/拆箱的迹象。但是我还是很怀疑,所以我用 -print编译了它():
[[syntax trees at end of cleanup]]// Scala source: X.scala
package <empty> {
class X extends java.lang.Object with ScalaObject {
def foo(ls: Array[Long]): Array[Double] = scala.this.Predef.longArrayOps(ls).map({
(new anonymous class X$$anonfun$foo$1(X.this): Function1)
}, scala.this.Array.canBuildFrom(reflect.this.Manifest.Double())).$asInstanceOf[Array[Double]]();
def this(): X = {
X.super.this();
()
}
};
@SerialVersionUID(0) final <synthetic> class X$$anonfun$foo$1 extends scala.runtime.AbstractFunction1$mcDJ$sp with Serializable {
final def apply(x$1: Long): Double = X$$anonfun$foo$1.this.apply$mcDJ$sp(x$1);
<specialized> def apply$mcDJ$sp(v1: Long): Double = v1.toDouble();
final <bridge> def apply(v1: java.lang.Object): java.lang.Object = scala.Double.box(X$$anonfun$foo$1.this.apply(scala.Long.unbox(v1)));
def this($outer: X): anonymous class X$$anonfun$foo$1 = {
X$$anonfun$foo$1.super.this();
()
}
}
}

关于这段代码的主要观察是创建的匿名函数专门用于 Long => Doublemap功能由 longArrayOps(ls).map 提供( ArrayOps 不是专门的)。

问题是 :“在这个例子中是否发生装箱/拆箱?”

最佳答案

可能有拳击正在进行。你要看看实际位置在哪里map - 调用:

27:  invokeinterface #46,  3; //InterfaceMethod scala/collection/TraversableLike.map:(Lscala/Function1;Lscala/collection/generic/CanBuildFrom;)Ljava/lang/Object;

在运行时,这应该转到 ArrayOps#ofLong .自 ArrayOps不是专业的,您的 map 不太可能- 不打拳击就打通电话。

要确定,您可以尝试通过字节码跟踪调用(可能很困难,因为在您的函数中您可能会遇到运行时调度)或使用调试器单步执行(很难,因为大多数调试器不显示字节码,但是您可以将断点设置为 Scala 或 Java 的装箱方法)。

出于实际原因,我们发现如果在字节码中进行装箱可能无关紧要,因为对于热方法,Hotspot 编译器有时会设法完全内联标准的高阶函数调用链,在这种情况下可以消除装箱。

关于scala - 如何在 Scala 中发现装箱/拆箱,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/6494860/

30 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com