日韩性视频-久久久蜜桃-www中文字幕-在线中文字幕av-亚洲欧美一区二区三区四区-撸久久-香蕉视频一区-久久无码精品丰满人妻-国产高潮av-激情福利社-日韩av网址大全-国产精品久久999-日本五十路在线-性欧美在线-久久99精品波多结衣一区-男女午夜免费视频-黑人极品ⅴideos精品欧美棵-人人妻人人澡人人爽精品欧美一区-日韩一区在线看-欧美a级在线免费观看

歡迎訪問 生活随笔!

生活随笔

當前位置: 首頁 > 编程资源 > 编程问答 >内容正文

编程问答

深入理解 JVM Class文件格式(五)

發布時間:2023/12/4 编程问答 32 豆豆
生活随笔 收集整理的這篇文章主要介紹了 深入理解 JVM Class文件格式(五) 小編覺得挺不錯的,現在分享給大家,幫大家做個參考.

(8) CONSTANT_Class_info

常量池中的一個CONSTANT_Class_info, 可以看做是CONSTANT_Class數據類型的一個實例。 他是對類或者接口的符號引用。 它描述的可以是當前類型的信息, 也可以描述對當前類的引用, 還可以描述對其他類的引用。 也就是說, 如果訪問了一個類字段, 或者調用了一個類的方法, 對這些字段或方法的符號引用, 必須包含它們所在的類型的信息, CONSTANT_Class_info就是對字段或方法符號引用中類型信息的描述。

CONSTANT_Class_info的第一個字節是tag, 值為7, 也就是說, 當虛擬機訪問到一個常量池中的數據項, 如果發現它的tag值為7, 就可以判斷這是一個CONSTANT_Class_info 。 tag下面的兩個字節是一個叫做name_index的索引值, 它指向一個CONSTANT_Utf8_info, 這個CONSTANT_Utf8_info中存儲了CONSTANT_Class_info要描述的類型的全限定名。 全限定名的概念在前面的博文 深入理解 JVM Class文件格式(二) 中描述過, 不熟悉的同學可以先閱讀這篇文章。

此外要說明的是, java中數組變量也是對象, 那么數組也就有相應的類型, 并且數組的類型也是使用CONSTANT_Class_info描述的, 并且數組類型和普通類型的描述有些區別。 普通類型的CONSTANT_Class_info中存儲的是全限定名, 而數組類型對應的CONSTANT_Class_info中存儲的是數組類型相對應的描述符字符串。 舉例說明:

與Object類型對應的CONSTANT_Class_info中存儲的是: java/lang/Object
與Object[]類型對應的CONSTANT_Class_info中存儲的是: [Ljava/lang/Object;

下面看CONSTANT_Class_info的存儲布局:

例如, 如果在一個類中引用了System這個類, 那么就會在這個類的常量池中出現以下信息:

(9) CONSTANT_Fieldref_info

常量池中的一個CONSTANT_Fieldref_info, 可以看做是CONSTANT_Field數據類型的一個實例。 該數據項表示對一個字段的符號引用, 可以是對本類中的字段的符號引用, 也可以是對其他類中的字段的符號引用, 可以是對成員變量字段的符號引用, 也可以是對靜態變量的符號引用, 其中ref三個字母就是reference的簡寫。 之前的文章中, “符號引用”這個名詞出現了很多次, 可能有的同學一直不是很明白, 等介紹完CONSTANT_Fieldref_info, 就可以很清晰的了解什么是符號引用。 下面分析CONSTANT_Fieldref_info中的內容都存放了什么信息。

和其他類型的常量池數據項一樣, 它的第一個字節也必然是tag, 它的tag值為9 。 也就是說, 當虛擬機訪問到一個常量池中的一項數據, 如果發現這個數據的tag值為9, 就可以確定這個被訪問的數據項是一個CONSTANT_Fieldref_info, 并且知道這個數據項表示對一個字段的符號引用。

tag值下面的兩個字節是一個叫做class_index的索引值, 它指向一個CONSTANT_Class_info數據項, 這個數據項表示被引用的字段所在的類型, 包括接口。 所以說, CONSTANT_Class_info可以作為字段符號引用的一部分。

class_index以下的兩個字節是一個叫做name_and_type_index的索引, 它指向一個CONSTANT_NameAndType_info, 這個CONSTANT_NameAndType_info前面的博客中已經解釋過了, 不明白的朋友可以先看前面的博客:深入理解JVM Class文件格式(三) 。 這個CONSTANT_NameAndType_info描述的是被引用的字段的名稱和描述符。 我們在前面的博客中也提到過, CONSTANT_NameAndType_info可以作為字段符號引用的一部分。

到此, 我們可以說, CONSTANT_Fieldref_info就是對一個字段的符號引用, 這個符號引用包括兩部分, 一部分是該字段所在的類, 另一部分是該字段的字段名和描述符。 這就是所謂的 “對字段的符號引用” 。

下面結合實際代碼來說明, 代碼如下:

package com.jg.zhang;public class TestInt {int a = 10;void print(){System.out.println(a);} }

在print方法中, 引用了本類中的字段a。 代碼很簡單, 我們一眼就可以看到print方法中是如何引用本類中定義的字段a的。 那么在class文件中, 對字段a的引用是如何描述的呢? 下面我們將這段代碼使用javap反編譯, 給出簡化后的反編譯結果:

Constant pool:#1 = Class #2 // com/jg/zhang/TestInt#2 = Utf8 com/jg/zhang/TestInt......#5 = Utf8 a#6 = Utf8 I......#12 = Fieldref #1.#13 // com/jg/zhang/TestInt.a:I#13 = NameAndType #5:#6 // a:I......{void print();flags:Code:stack=2, locals=1, args_size=10: getstatic #19 // Field java/lang/System.out:Ljava/io/PrintStream;3: aload_04: getfield #12 // Field a:I7: invokevirtual #25 // Method java/io/PrintStream.println:(I)V10: return }

可以看到, print方法的位置為4的字節碼指令getfield引用了索引為12的常量池數據項, 常量池中索引為12的數據項是一個CONSTANT_Fieldref_info, 這個CONSTANT_Fieldref_info又引用了索引為1和13的兩個數據項, 索引為1的數據項是一個CONSTANT_Class_info, 這個CONSTANT_Class_info數據項又引用了索引為2的數據項, 索引為2的數據項是一個CONSTANT_Utf8_info , 他存儲了字段a所在的類的全限定名com/jg/zhang/TestInt 。 而CONSTANT_Fieldref_info所引用的索引為13的數據項是一個CONSTANT_NameAndType_info, 它又引用了兩個數據項, 分別為第5項和第6項, 這是兩個CONSTANT_Utf8_info , 分別存儲了字段a的字段名a, 和字段a的描述符I 。

下面給出內存布局圖, 這個圖中涉及的東西有點多, 因為CONSTANT_Fieldref_info引用了CONSTANT_Class_info和CONSTANT_NameAndType_info, CONSTANT_Class_info又引用了一個CONSTANT_Utf8_info , 而CONSTANT_NameAndType_info又引用了兩個CONSTANT_Utf8_info 。

(10) CONSTANT_Methodref_info

常量池中的一個CONSTANT_Methodref_info, 可以看做是CONSTANT_Methodref數據類型的一個實例。 該數據項表示對一個類中方法的符號引用, 可以是對本類中的方法的符號引用, 也可以是對其他類中的方法的符號引用, 可以是對成員方法字段的符號引用, 也可以是對靜態方法的符號引用,但是不會是對接口中的方法的符號引用。 其中ref三個字母就是reference的簡寫。 在上一小節中介紹了CONSTANT_Fieldref_info, 它是對字段的符號引用, 本節中介紹的CONSTANT_Methodref_info和CONSTANT_Fieldref_info很相似。既然是符號“引用”, 那么只有在原文件中調用了一個方法, 常量池中才有和這個被調用方法的相對應的符號引用, 即存在一個CONSTANT_Methodref_info。 如果只是在類中定義了一個方法, 但是沒調用它, 則不會在常量池中出現和這個方法對應的CONSTANT_Methodref_info 。

和其他類型的常量池數據項一樣, 它的第一個字節也必然是tag, 它的tag值為10 。 也就是說, 當虛擬機訪問到一個常量池中的一項數據, 如果發現這個數據的tag值為10, 就可以確定這個被訪問的數據項是一個CONSTANT_Methodref_info, 并且知道這個數據項表示對一個方法的符號引用。

tag值下面的兩個字節是一個叫做class_index的索引值, 它指向一個CONSTANT_Class_info數據項, 這個數據項表示被引用的方法所在的類型。 所以說, CONSTANT_Class_info可以作為方法符號引用的一部分。

class_index以下的兩個字節是一個叫做name_and_type_index的索引, 它指向一個CONSTANT_NameAndType_info, 這個CONSTANT_NameAndType_info前面的博客中已經解釋過了, 不明白的朋友可以先看前面的博客:深入理解JVM Class文件格式(三) 。 這個CONSTANT_NameAndType_info描述的是被引用的方法的名稱和描述符。 我們在前面的博客中也提到過, CONSTANT_NameAndType_info可以作為方法符號引用的一部分。

到此, 我們可以知道, CONSTANT_Methodref_info就是對一個方法的符號引用, 這個符號引用包括兩部分, 一部分是該方法所在的類, 另一部分是該方法的方法名和描述符。 這就是所謂的 “對方法的符號引用” 。下面結合實際代碼來說明, 代碼如下:

package com.jg.zhang;public class Programer {Computer computer;public Programer(Computer computer){this.computer = computer;}public void doWork(){computer.calculate();} }package com.jg.zhang;public class Computer {public void calculate() {System.out.println("working...");} }

上面的代碼包括兩個類, 其中Programer類引用了Computer類, 在Programer類的doWork方法中引用(調用)了Computer類的calculate方法。源碼中對一個方法的描述形式我們再熟悉不過了, 現在我們就反編譯Programer, 看看Programer中對Computer的doWork方法的引用, 在class文件中是如何描述的。

下面給出Programer的反編譯結果, 其中省去了一些不相關的信息:

Constant pool: .........#12 = Utf8 ()V#20 = Methodref #21.#23 // com/jg/zhang/Computer.calculate:()V#21 = Class #22 // com/jg/zhang/Computer#22 = Utf8 com/jg/zhang/Computer#23 = NameAndType #24:#12 // calculate:()V#24 = Utf8 calculate{com.jg.zhang.Computer computer; flags:.........public void doWork();flags: ACC_PUBLICCode:stack=1, locals=1, args_size=10: aload_01: getfield #13 // Field computer:Lcom/jg/zhang/Computer;4: invokevirtual #20 // Method com/jg/zhang/Computer.calculate:()V7: return }

可以看到, doWork方法的位置為4的字節碼指令invokevirtual引用了索引為20的常量池數據項, 常量池中索引為20的數據項是一個CONSTANT_Methodref_info, 這個CONSTANT_Methodref_info又引用了索引為21和23的兩個數據項, 索引為21的數據項是一個CONSTANT_Class_info, 這個CONSTANT_Class_info數據項又引用了索引為22的數據項, 索引為22的數據項是一個CONSTANT_Utf8_info , 他存儲了被引用的Computer類中的calculate方法所在的類的全限定名com/jg/zhang/Computer 。 而CONSTANT_Methodref_info所引用的索引為23的數據項是一個CONSTANT_NameAndType_info, 它又引用了兩個數據項, 分別為第24項和第12項, 這是兩個CONSTANT_Utf8_info , 分別存儲了被引用的方法calculate的方法名calculate, 和該方法的描述符()V 。

下面給出內存布局圖, 這個圖中涉及的東西同樣有點多, 因為CONSTANT_Methodref_info引用了CONSTANT_Class_info和CONSTANT_NameAndType_info, CONSTANT_Class_info又引用了一個CONSTANT_Utf8_info , 而CONSTANT_NameAndType_info又引用了兩個CONSTANT_Utf8_info 。

(11) CONSTANT_InterfaceMethodref_info

常量池中的一個CONSTANT_InterfaceMethodref_info, 可以看做是CONSTANT_InterfaceMethodref數據類型的一個實例。 該數據項表示對一個接口方法的符號引用, 不能是對類中的方法的符號引用。 其中ref三個字母就是reference的簡寫。 在上一小節中介紹了CONSTANT_Methodref_info, 它是對類中的方法的符號引用, 本節中介紹的CONSTANT_InterfaceMethodref和CONSTANT_Methodref_info很相似。既然是符號“引用”, 那么只有在原文件中調用了一個接口中的方法, 常量池中才有和這個被調用方法的相對應的符號引用, 即存在一個CONSTANT_InterfaceMethodref。 如果只是在接口中定義了一個方法, 但是沒調用它, 則不會在常量池中出現和這個方法對應的CONSTANT_InterfaceMethodref 。

和其他類型的常量池數據項一樣, 它的第一個字節也必然是tag, 它的tag值為11 。 也就是說, 當虛擬機訪問到一個常量池中的一項數據, 如果發現這個數據的tag值為11, 就可以確定這個被訪問的數據項是一個CONSTANT_InterfaceMethodref, 并且知道這個數據項表示對一個接口中的方法的符號引用。

tag值下面的兩個字節是一個叫做class_index的索引值, 它指向一個CONSTANT_Class_info數據項, 這個數據項表示被引用的方法所在的接口。 所以說, CONSTANT_Class_info可以作為方法符號引用的一部分。

class_index以下的兩個字節是一個叫做name_and_type_index的索引, 它指向一個CONSTANT_NameAndType_info, 這個CONSTANT_NameAndType_info前面的博客中已經解釋過了, 不明白的朋友可以先看前面的博客:深入理解JVM Class文件格式(三) 。 這個CONSTANT_NameAndType_info描述的是被引用的方法的名稱和描述符。 我們在前面的博客中也提到過, CONSTANT_NameAndType_info可以作為方法符號引用的一部分。

到此, 我們可以知道, CONSTANT_InterfaceMethodref就是對一個接口中的方法的符號引用, 這個符號引用包括兩部分, 一部分是該方法所在的接口, 另一部分是該方法的方法名和描述符。 這就是所謂的 “對接口中的方法的符號引用” 。

下面結合實際代碼來說明, 代碼如下:

public class Plane {IFlyable flyable;void flyToSky(){flyable.fly();} }package com.jg.zhang;public interface IFlyable {void fly(); }

在上面的代碼中, 定義一個類Plane, 在這個類中有一個IFlyable接口類型的字段flyable, 然后在Plane的flyToSky方法中調用了IFlyable中的fly方法。 這就是源代碼中對一個接口中的方法的引用方式, 下面我們反編譯Plane, 看看在class文件層面, 對一個接口中的方法的引用是如何描述的。
下面給出反編譯結果, 為了簡潔期間, 省略了一些不相關的內容:

Constant pool: .........#8 = Utf8 ()V#19 = InterfaceMethodref #20.#22 // com/jg/zhang/IFlyable.fly:()V#20 = Class #21 // com/jg/zhang/IFlyable#21 = Utf8 com/jg/zhang/IFlyable#22 = NameAndType #23:#8 // fly:()V#23 = Utf8 fly{.........com.jg.zhang.IFlyable flyable;flags:.........void flyToSky();flags:Code:stack=1, locals=1, args_size=10: aload_01: getfield #17 // Field flyable:Lcom/jg/zhang/IFlyable;4: invokeinterface #19, 1 // InterfaceMethod com/jg/zhang/IFlyable.fly:()V9: return}

可以看到, flyToSky方法的位置為4的字節碼指令invokeinterface引用了索引為19的常量池數據項, 常量池中索引為19的數據項是一個CONSTANT_InterfaceMethodref_info, 這個CONSTANT_InterfaceMethodref_info又引用了索引為20和22的兩個數據項, 索引為20的數據項是一個CONSTANT_Class_info, 這個CONSTANT_Class_info數據項又引用了索引為21的數據項, 索引為21的數據項是一個CONSTANT_Utf8_info , 他存儲了被引用的方法fly所在的接口的全限定名com/jg/zhang/IFlyable 。 而CONSTANT_InterfaceMethodref_info所引用的索引為22的數據項是一個CONSTANT_NameAndType_info, 它又引用了兩個數據項, 分別為第23項和第8項, 這是兩個CONSTANT_Utf8_info , 分別存儲了被引用的方法fly的方法名fly, 和該方法的描述符()V 。

下面給出內存布局圖, 這個圖中涉及的東西同樣有點多, 因為CONSTANT_InterfaceMethodref_info引用了CONSTANT_Class_info和CONSTANT_NameAndType_info, CONSTANT_Class_info又引用了一個CONSTANT_Utf8_info , 而CONSTANT_NameAndType_info又引用了兩個CONSTANT_Utf8_info 。

總結

到此為止, class文件中的常量池部分就已經講解完了。 進行一下總結。對于深入理解Java和JVM , 理解class文件的格式至關重要, 而在class文件中, 常量池是一項非常重要的信息。 常量池中有11種數據項, 這個11種數據項存儲了各種信息, 包括常量字符串, 類的信息, 方法的符號引用, 字段的符號引用等等。 常量池中的數據項通過索引來訪問, 訪問形式類似于數組。 常量池中的各個數據項之前會通過索引相互引用, class文件的其他地方也會引用常量池中的數據項 , 如方法的字節碼指令。

在下面的文章中, 會繼續介紹class文件中, 位于常量池以下的其他信息。 這些信息包括:對本類的描述, 對父類的描述, 對實現的接口的描述, 本類中聲明的字段的描述, 本類匯總定義的方法的描述,還有各種屬性。

總結

以上是生活随笔為你收集整理的深入理解 JVM Class文件格式(五)的全部內容,希望文章能夠幫你解決所遇到的問題。

如果覺得生活随笔網站內容還不錯,歡迎將生活随笔推薦給好友。

主站蜘蛛池模板: 成人手机视频 | 强伦人妻一区二区三区 | 亚洲午夜视频 | 绯色av蜜臀vs少妇 | 九九爱视频 | 色无极影院亚洲 | 无码国产精品高潮久久99 | 少妇搡bbbb搡bbb搡小说 | 国产视频精品免费 | 国产精品第72页 | 激情五月婷婷 | 国产精品午夜久久 | 国产一二三区免费视频 | 福利片在线看 | av一区三区 | a天堂v| 色老板av | 午夜成人鲁丝片午夜精品 | 粉嫩久久99精品久久久久久夜 | 99热3 | 国产一区二区三区免费播放 | 久久国产精品二区 | 久久亚洲精精品中文字幕早川悠里 | 久久久久这里只有精品 | 午夜特级毛片 | 一级片免费观看视频 | 国产经典久久 | 精品不卡一区二区三区 | 国产区一二三 | 在线观看成年人网站 | 少妇又色又爽又黄的视频 | 日韩精品视频免费在线观看 | 奇米影视播放器 | 97人人模人人爽人人少妇 | 色香蕉视频 | 国模无码一区二区三区 | 亚洲性综合网 | 久久123 | 欧美波霸影院 | 久久天天躁狠狠躁夜夜躁 | 欧美性生交大片免费看 | 欧美性色黄 | 欧洲一区二区三区在线 | 欧美一区永久视频免费观看 | 欧美激情喷水 | 污的视频在线观看 | 波多野结衣高清电影 | 久久精品网址 | 五月天激情电影 | 91手机视频在线观看 | 国产免费激情视频 | 天天射网 | 日本视频二区 | 韩国av在线播放 | 蜜臀aⅴ免费一区二区 | 欧美熟妇乱码在线一区 | 操xxxx| 亚洲视频在线观看网址 | 亚洲精品成人无码毛片 | 中国女人av | 国产精品国产三级国产 | 粉嫩av一区二区 | 欧美第五页 | 国产又粗又长视频 | 色骚网 | 福利国产片 | 91精品视频国产 | 欧美老熟| 日韩福利视频 | 国产免费专区 | 91看片成人 | 久久99久久99精品免观看粉嫩 | 免费黄网在线看 | 正在播放超嫩在线播放 | 国产a级大片 | 99久久亚洲精品日本无码 | 国产免费小视频 | 欧美亚洲不卡 | 日韩精品一区在线 | 欧美熟妇激情一区二区三区 | 日本欧美激情 | 女人高潮娇喘1分47秒 | 99精品视频免费在线观看 | 国产调教一区 | 国产一区视频网站 | 伊人影视大全 | www在线| 熟女肥臀白浆大屁股一区二区 | 超碰免费在线观看 | av影院在线播放 | 精品国产亚洲av麻豆 | 日本男人的天堂 | av色吧 | 欧美乱妇狂野欧美视频 | 91视频国产精品 | 绿帽人妻精品一区二区 | 精射女上司 | 色小说香蕉 | 99精品偷自拍 |