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 文件格式中有自己的编码。