Scala 的多个参数列表如何编码为 JVM 字节码
How Scala's multiple parameter lists get encoded into JVM bytecode
在Scala中,下面两个函数是不同的:
def paren(): Int = 42
def noparen: Int = 42
第一个有 1 个参数列表,参数为零,而下一个有 0 个参数列表。
然而,当用 javap -v
:
查看时,它们的字节码是相同的
public int paren();
Signature: ()I
flags: ACC_PUBLIC
Code:
stack=1, locals=1, args_size=1
0: bipush 42
2: ireturn
LocalVariableTable:
Start Length Slot Name Signature
0 3 0 this LParentheses$;
LineNumberTable:
line 4: 0
public int noparen();
Signature: ()I
flags: ACC_PUBLIC
Code:
stack=1, locals=1, args_size=1
0: bipush 42
2: ireturn
LocalVariableTable:
Start Length Slot Name Signature
0 3 0 this LParentheses$;
LineNumberTable:
line 5: 0
Scala 编译器将参数列表的维度存储在哪里?
虽然没有明确提及,
SID-10 建议这些信息将存储在 ScalaSignature 中。
为了对此进行测试,我使用了以下代码,并且 javap -v
和您一样。
@Deprecated //add an annotation for reference
class Test {
def test: Unit = ???
def test2(): Unit = ???
}
在最后,有这样的输出:
SourceFile: "Test.scala"
RuntimeVisibleAnnotations:
0: #6()
1: #7(#8=s#9)
Error: unknown attribute
ScalaSig: length = 0x3
05 00 00
其中 #6
是 @Deprecated
,#7(#8=s#9)
是 @scala.reflect.ScalaSignature(bytes=...)
。因此,尽管有多种方法,并且 class 也有自己的签名,但只有一个 ScalaSignature
注释以某种二进制格式对所有附加签名信息进行编码。
您已经指向 SID-10 in your ,其中指出签名已压缩(这很明显,因为其中没有可识别的 class 名称),并且 ScalaSig
class 文件属性在 Scala 2.8 之前用于此。 (更改的原因被解释为运行时的反射访问——(至少未知的)属性不被 JVM 保留;适当保留的注释被保留。)
需要注意的另一件事是,虽然 Scala 签名是 Java 签名的超集,但 Java 签名仍然必须是唯一的 - 在运行时,JVM 不关心斯卡拉
PS:其他JVM语言也是这样做的;我知道肯定是这样的一个是 AspectJ。我认为泛型也可以通过这种方式实现,但事实并非如此;他们在 class 文件格式中有自己的编码。
在Scala中,下面两个函数是不同的:
def paren(): Int = 42
def noparen: Int = 42
第一个有 1 个参数列表,参数为零,而下一个有 0 个参数列表。
然而,当用 javap -v
:
public int paren();
Signature: ()I
flags: ACC_PUBLIC
Code:
stack=1, locals=1, args_size=1
0: bipush 42
2: ireturn
LocalVariableTable:
Start Length Slot Name Signature
0 3 0 this LParentheses$;
LineNumberTable:
line 4: 0
public int noparen();
Signature: ()I
flags: ACC_PUBLIC
Code:
stack=1, locals=1, args_size=1
0: bipush 42
2: ireturn
LocalVariableTable:
Start Length Slot Name Signature
0 3 0 this LParentheses$;
LineNumberTable:
line 5: 0
Scala 编译器将参数列表的维度存储在哪里?
虽然没有明确提及,
SID-10 建议这些信息将存储在 ScalaSignature 中。
为了对此进行测试,我使用了以下代码,并且 javap -v
和您一样。
@Deprecated //add an annotation for reference
class Test {
def test: Unit = ???
def test2(): Unit = ???
}
在最后,有这样的输出:
SourceFile: "Test.scala"
RuntimeVisibleAnnotations:
0: #6()
1: #7(#8=s#9)
Error: unknown attribute
ScalaSig: length = 0x3
05 00 00
其中 #6
是 @Deprecated
,#7(#8=s#9)
是 @scala.reflect.ScalaSignature(bytes=...)
。因此,尽管有多种方法,并且 class 也有自己的签名,但只有一个 ScalaSignature
注释以某种二进制格式对所有附加签名信息进行编码。
您已经指向 SID-10 in your ScalaSig
class 文件属性在 Scala 2.8 之前用于此。 (更改的原因被解释为运行时的反射访问——(至少未知的)属性不被 JVM 保留;适当保留的注释被保留。)
需要注意的另一件事是,虽然 Scala 签名是 Java 签名的超集,但 Java 签名仍然必须是唯一的 - 在运行时,JVM 不关心斯卡拉
PS:其他JVM语言也是这样做的;我知道肯定是这样的一个是 AspectJ。我认为泛型也可以通过这种方式实现,但事实并非如此;他们在 class 文件格式中有自己的编码。