2015-05-07 41 views
4

因此,這裏的例子:什麼做「開始」和LocalVariableTable「長度」屬性意味着

LocalVariableTable: 
     Start Length Slot Name Signature 
       0  133  0 this Lcom/my/class/Test; 
       2  131  1  a I 
       4  129  2  b I 
       7  126  3  i I 
       10  123  4 i2 I 
       16  117  5 o1 Ljava/lang/Integer; 
       31  102  6 o2 Ljava/lang/Integer; 

什麼是啓動和長度是什麼意思?爲什麼長度有它的價值?爲什麼相同類型(整數)的長度不同?爲什麼長度可以改變,當我添加一些東西給類並重新編譯它而不觸及特定的局部變量?

回答

7

開始是該變量可見的起始字節碼偏移量。長度是此變量可見的字節碼字節數。通常起始點指向首先分配變量的字節碼指令,或者指向方法參數0和this。在你的情況下,似乎所有的變量在方法的末尾都是有效的(每個變量爲start+length = 133),但是如果你在塊內聲明瞭一些變量,它們的作用域會縮短。

請注意,局部變量表(LVT)是一個可選的調試信息。程序不需要執行,編譯期間可以使用-g:none關閉。該表的主要目的是爲了使調試更加方便:讓您可以爲每個字節碼確定哪些變量當前可見,以便在變量窗格中顯示它們並在離開變量範圍後隱藏它們。此表也被Java反編譯器和代碼分析器如FindBugs使用。

+0

非常感謝您的回答。如果你不介意,我想根據你的回答提出另一個問題。如果你說LVT是可選的,它的目的只是用於調試,那麼如何將以局部變量索引作爲參數(例如,aload)的java操作碼正在工作呢?當沒有LVT時,局部變量信息是否存儲在其他地方? – dhblah

+1

「this」(對於非靜態方法)和方法參數(每個「long」/「double」2個槽,其他類型爲1個槽)將自動使用第一個槽,這可以通過方法簽名來決定。在那之後,如果JVM看到一個用於新插槽的存儲指令,它就簡單地分配這個插槽(或者'lstore' /'dstore'的兩個插槽),並根據操作碼設置其類型。在已驗證的字節碼中,不應該有從未知時隙加載的加載指令(不是由方法參數或先前的存儲指令佔用)。 –

+0

所以基本上你會說,雖然LVT可以在編譯時被丟棄,但它僅用於信息目的。並且所有與JVM所需的局部變量相關的數據都存儲在堆棧幀中的局部變量數組中。因此,本地變量可以通過它們在該數組中的索引來尋址,而LVT僅包含補充信息,以便在調試期間在調試窗格的正確步驟中顯示\隱藏本地變量。 – dhblah

1

根據jsl

內部本地variabale表

u2 local_variable_table_length; 
    { u2 start_pc; 
     u2 length; 
     u2 name_index; 
     u2 descriptor_index; 
     u2 index; 
    } 

的local_variable_table陣列中的每個條目指示的範圍內碼陣列 偏移在其內的局部變量具有一個值的。它還將指數 指示到可以找到該局部變量的當前幀的局部變量數組中。

現在爲起點和長度屬性JSL說

start_pc,長度

陣列在區間[start_pc,start_pc +長度),即, start_pc包容和start_pc之間+長度獨家。

The value of start_pc must be a valid index into the code array of this 

代碼屬性並且必須是指令的操作碼的索引。

The value of start_pc + length must either be a valid index into 

這個代碼屬性的代碼陣列和是一個指令的操作碼 的索引,或者它必須超出碼陣列的端部的第一索引。

所以基本上開始對應於你LineNumberTable