java实体字节属性定义_Java字节码方法表与属性表详解
而這些字節(jié)其實對應(yīng)的信息是它:
所以問題就來了,aload_0不是助記符信息么,怎么就能夠跟字節(jié)碼文件中的字節(jié)對應(yīng)上呢?所謂助記符其實也就是幫忙我們?nèi)ビ洃浀姆?#xff0c;在底層其實也是對應(yīng)的一個個十六進制的數(shù)字的,其它aload_0對應(yīng)的就是2A這個十六進制數(shù)字,憑什么這么說?因為有jclasslib這么好的工具能幫我們對應(yīng)上,將鼠標放在助記符上發(fā)現(xiàn)是一個可以點的鏈接,如下:
點一下“aload_0”發(fā)現(xiàn)居然鏈到了oracle的官網(wǎng)上的說明上去了,如下:
所以第一個字節(jié)已經(jīng)分析完了,確實是跟助記符對應(yīng)上了,接著來分析第二個字節(jié):
而在jsclasslib中對應(yīng)的第二個助記符是“invokespecial”,點擊鏈到官網(wǎng)看一下:
而它的作用可以理解成就是調(diào)用父類的方法,很明顯對于咱們自定義的子類肯定會去調(diào)用父類的構(gòu)造方法,而這個助記符是有參數(shù)的:
其實也就是往后的兩個字節(jié)就是該助記符所對應(yīng)的參數(shù),如下:
對應(yīng)常量池為:
也就是構(gòu)造方法嘛,如jsclasslib所示:
接下來繼續(xù)往下走一個字節(jié):
又對應(yīng)aload_0,如下:
接著再往后看一個字節(jié):
其實它就是對應(yīng)下一個助記符,如下:
為啥如此任性呢,因為點擊查看一下說明就曉了啦:
為啥要push一個1呢?實際就是給咱們定義的成員變量a賦值,如下:
可見,該變量的賦值是在默認構(gòu)造函數(shù)中進行的,而不是直接進行賦值的,這也就是分析字節(jié)碼文件的好處,可以更加真實的發(fā)現(xiàn)底層細節(jié)。
接下來再數(shù)一個字節(jié):
當(dāng)然它又對應(yīng)另一個助記符嘍,如下:
點擊看一下官網(wǎng)說明:
接下來該助記符是攜帶有參數(shù)的,所以再往后數(shù)兩個字節(jié):
對應(yīng)常量池:
也就是給MyTest1的成員變量a賦值為1。
接下來再數(shù)一個字節(jié):
對應(yīng)于如下助記符:
點擊確認一下:
至此整個構(gòu)造方法就已經(jīng)執(zhí)行完了。發(fā)現(xiàn)通過分析字節(jié)碼也能獲得不少新知識嘛,僅通過這個構(gòu)造函數(shù)的執(zhí)行流程就能知道了對于我們定義的成員變量原來是在構(gòu)造方法中進行賦值而非直接賦值的,還是挺有價值的。
好,方法的code分析完之后,則就得往下進行分析了,先來查看一下結(jié)構(gòu)類型:
也就是再數(shù)兩個字節(jié),看一下:
說明該方法木有異常信息,所以接下來的異常表就不會顯示在字節(jié)文件當(dāng)中了:
其中關(guān)于異常還需解釋一下:
exception_table,這里存放的是處理異常的信息。
每個exception_table表項由start_pc、end_pc、handler_pc、catch_type組成。
start_pc和end_pc表示在code數(shù)組中的從start_pc到end_pc處(包含start_pc,不包含end_pc)的指令拋出的異常會由這個表項來處理。
handler_pc表示處理異常的代碼的開始處。catch_type表示會處理的異常類型,它指向常量池里的一個異常類。當(dāng)catch_type為0時,表示處理所有的異常。
接下來就到屬性相關(guān)的東東了,如下:
所以往下數(shù)2個字節(jié):
說明該方法有兩個屬性,往下數(shù)兩個字節(jié)則是第一個屬性的名字索引,如下:
也就是對應(yīng)第10的常量池,為:
該屬性用來表示code數(shù)組中的字節(jié)碼和Java代碼行數(shù)之間的關(guān)系。這個屬性可以用來在調(diào)試的時候定位代碼執(zhí)行的行數(shù)。而該屬性的結(jié)構(gòu)為:
其中attribute_name_index就是常量索引10,接下來數(shù)4個字節(jié)則是屬性的長度attribute_length,如下:
也就是屬性的長度為10,也就是接下來10個字節(jié)則為LineNumberTable的屬性信息,如下:
看一下jclasslib:
下面具體來分析一下這10個字節(jié),根據(jù)結(jié)構(gòu)體來看:
先2個字節(jié)表示屬性表有幾對映射,如下:
說明有兩對映射,然后再回到結(jié)構(gòu)體中,每對映射的內(nèi)容為:
每對占4個字節(jié),先看第一對映射:
也就是start_pc=0;line_number=3,對應(yīng)于jclasslib:
由于咱們源代碼木有構(gòu)造方法,所以字節(jié)碼對應(yīng)源代碼就在第3行,如下:
接下來看第二對映射:
也就是start_pc=4;line_number=4,對應(yīng)于jclasslib:
因為成員變量的賦值是在構(gòu)造方法中完成的,所以對應(yīng)第4行代碼:
好,方法的第一個屬性已經(jīng)完了,接下來以同樣的順序來查看方法的第二個屬性信息了,走2個字節(jié)來看屬性名稱索引,如下:
對應(yīng)第11個常量池索引,如下:
它的結(jié)構(gòu)跟LineNumberTable差不多的,往后數(shù)四個字節(jié)則是局部變量表所占的長度:
長度為12,如jclasslib所示:
然后往后數(shù)12個字節(jié)則是局部變量的具體信息,首先兩個字節(jié)則為局部變量的個數(shù),如下:
呃~~構(gòu)造方法哪來的局部變量呢,好奇怪,先不管先來把其它字節(jié)分析完,再往后四個字節(jié)表示start_pc和length,如下:
如jclasslib所示:
接下來則為局部變量的索引為0,也就是第一個局部變量:
再往后兩個字節(jié)則是局部變量對應(yīng)常量池的索引,如下:
再接下來兩個字節(jié)則是對該局部變量的一個描述常量索引,如下:
所以對應(yīng)jclasslib中可以看到:
那思考一下為啥在構(gòu)造方法中會有一個this的局部變量呢?我們知道在所有方法中我們都能使用this關(guān)鍵字來訪問當(dāng)前的對象,而從字節(jié)層面來講其實this是作為方法的第一個參數(shù)傳進來的,也就是說對于Java的一個實例方法而言最少會有一個this的局部變量存在!
還剩最后兩個字節(jié)則為stackmaptable信息,JDK1.6加入的,主要做校驗檢查的,因為0嘛所以后面肯定木有相關(guān)的信息了,這里就直接忽略,如下:
總結(jié)
以上是生活随笔為你收集整理的java实体字节属性定义_Java字节码方法表与属性表详解的全部內(nèi)容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: 网申民生in卡多久下卡
- 下一篇: JAVA_if或者怎么用,Java If