2015-08-18 76 views
4

在Scala中,下面的兩個功能不同的是:Scala的多個參數列表是如何被編碼成JVM字節碼

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編譯器存儲參數列表的尺寸是多少?

回答

3

爲了測試這個,我使用了以下代碼,並且使用了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=...)。因此,即使有多種方法,並且該類也有其自己的簽名,但只有一個註釋以某種二進制格式對所有附加簽名信息進行編碼。

你已經指出SID-10answer,它指出簽名壓縮(這是相當明顯的,因爲裏面還有沒有可識別的類名),以及用於此的ScalaSig類文件屬性在Scala 2.8之前。 (更改的原因被解釋爲在運行時反射訪問 - 至少未知的屬性不會被JVM保留;具有適當保留的註釋是。)

另外需要注意的一點是,雖然Scala簽名是Java簽名的超集,Java簽名仍然必須是唯一的 - 在運行時,JVM不關心Scala。 PS:這也是在其他JVM語言中完成的;但是,一個我知道的情況是AspectJ。我認爲泛型也可以用這種方式來實現,但它們不是;他們有自己的編碼類文件格式。

+0

Martin Odersky在Java 1.0時間框架內設計並實現了泛型,事實上,他編寫的Java編譯器已經提供了1.2(並且仍然是Oracle JDK和OpenJDK附帶的),只是泛型位被禁用。註釋僅在Java 5中添加。如果Annotations當時存在,或者泛型已經在後來被重新設計,那麼誰知道呢,也許我們現在已經將泛型化了。 –

1

雖然沒有明確提到它,

SID-10表明,這些信息將被存儲在ScalaSignature。