上篇文章提到過在Class結構表中,屬性表存在于Class表,字段表和方法表中,是為了 「描述額外的信息」 。
?屬性表在《JAVA虛擬機規范》中并沒有像其他數據一樣做嚴格的限制,我們甚至可以自己實現一個編譯器往Class結構的屬性表中注入額外的屬性信息,虛擬機運行時會忽略掉它識別不了的屬性。
?
屬性表屬性總覽
這張圖中按Class結構,字段表,方法表這三個維度進行了區分標注,將 「三者共有的屬性」 提取到最頂部的 「黃色橢圓」 中, 「藍色」 代表各自屬性表 「額外用到的屬性」 , 「紅色」 代表 「Code屬性中引用的其他屬性的集合」 。
引自《深入理解JAVA虛擬機》,讀者也可以看這下面的兩張圖:
屬性結構
首先表結構中的前兩個字節說明該屬性是叫什么名字,也就是什么類型的屬性,最終指向常量池中的CONSTANT_Utf8_info類型的常量。
?eg:Code,ConstantValue,SourceFile。。。等
?
接著用四個字節描述屬性值的長度,也就是說明屬性值所占用的字節數;
?除了第一個屬性名稱信息和該屬性描述的屬性長度,其他的就是屬性值了,因此該值(屬性值長度)固定為 整個屬性表長度-6個字節
?
最后列出屬性信息,有多少屬性信息呢?前四個字節已經列出了這個屬性包含多少個屬性,因此最后描述各個屬性的信息。
前兩個屬性是所有屬性都共有的,之后就不進行講解了。
常見屬性
Code
?只有方法內有方法體的方法表才會有這項屬性,像抽象方法,非defult接口方法是沒有這個屬性的(沒有方法體)
?
「該屬性用于存放 操作數棧最大深度, 本地變量表最大占用存儲空間, 方法中Catch塊定義的異常類型和數量, 編譯后方法體的字節碼指令和指令長度, 還有其他屬性」
首先先看下Code屬性表的結構:
1.「max_stack操作數棧最大深度」
先看下之前的這篇文章,Java程序運行是基于棧的操作,就是說的該項屬性。
通過指令從本地變量表中拿數據放到棧頂;將數據從棧頂保存到本地變量中;對棧頂兩個值進行運算后將結果壓入棧頂;將棧頂的值作為返回結果return.....等等這些都是通過操作數據結構棧來完成的。
?這項屬性描述了方法中操作數棧的最大深度,虛擬機運行時會根據這項屬性來分配棧幀中操作數棧的最大深度。
?
2.「max_locals局部變量表所需空間」
局部變量表最大占用的存儲空間,存儲的單位用的是Slot(變量槽),一個 Slot占用空間大小為32位。
存儲范圍:比如方法的參數,Catch塊中定義的異常類型,方法體中定義的局部變量。
?對于方法參數來說,根據實例方法(通過對象才能訪問)和靜態方法(通過類名就可以直接訪問)又有不同;實例方法的參數中第一個是this,該變量會在編譯時加入,而靜態方法則沒有這個變量。
?
存儲空間:對于小于32位的數據類型用一個變量槽,大于32位的用多個變量槽存儲(比如小于64位的數據類型double和long用兩個變量槽存儲)。優化:對變量限定作用域,如果變量超出了作用域范圍,那么存儲該變量的Slot進行存儲其他的變量,也就是重用變量槽。
?根據同時生存的最大局部變量數量和類型計算出max_locals的大小。
?
3.「code_length,code屬性用于表述方法體編譯后的字節碼指令長度和字節碼指令流」
?字節碼指令流,一個字節代表一條指令,即每條指令就是一個u1類型的單字節;u1數據類型取值范圍是0X00~0XFF,對應十進制為0到255。即u1可以表達256條指令,目前使用的大約只有200條
?
?方法體中不允許超過65535條字節碼指令,如果超出了編譯器拒絕編譯;但是code_length用的是u4長度值,可以達到2的32次冪,相當于指令長度只用了一半(u2長度)。
?
4.「exception_table_length,exception_table用于描述方法塊中Catch塊定義的異常數量和類型」
?如果方法體內部沒有catch塊則length為0,后面的字節不描述exception_table
?
在這里插入圖片描述
?Exception table:
from to target type
0 5 10 Class java/lang/Exception
0 5 21 any
10 16 21 any
?
Exceptions
該屬性和上面提到的exception_table描述的信息不一樣,exception_table是描述方法體中Catch塊中定義的異常數量和類型;而該項屬性是描述方法throws的異常數量和類型,通俗來說就是調用該方法需要catch的異常,也叫作受查異常。
?因此上面的excepitons_table描述方法體內部Catch的異常,Exceptions描述方法拋出的異常
?
結構:
LineNumberTable
?用于描述Java代碼行號和字節碼行號的對應關系,該項屬性可選擇是否輸出
?
?用處:當執行某段字節碼指令拋出異常時可以根據這個對應關系,提示開發者Java代碼對應的行號。
?
結構
-
JAVA
+關注
關注
19文章
2967瀏覽量
104733 -
Class
+關注
關注
0文章
53瀏覽量
19725 -
JVM
+關注
關注
0文章
158瀏覽量
12222
發布評論請先 登錄
相關推薦
評論