一区二区三区在线-一区二区三区亚洲视频-一区二区三区亚洲-一区二区三区午夜-一区二区三区四区在线视频-一区二区三区四区在线免费观看

服務器之家:專注于服務器技術及軟件下載分享
分類導航

PHP教程|ASP.NET教程|Java教程|ASP教程|編程技術|正則表達式|C/C++|IOS|C#|Swift|Android|VB|R語言|JavaScript|易語言|vb.net|

服務器之家 - 編程語言 - Java教程 - Java class文件格式之數據類型(二)_動力節點Java學院整理

Java class文件格式之數據類型(二)_動力節點Java學院整理

2020-11-17 11:06動力節點 Java教程

這篇文章主要介紹了Java 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要描述的類型的全限定名。 

此外要說明的是, 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的存儲布局:

Java class文件格式之數據類型(二)_動力節點Java學院整理

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

Java class文件格式之數據類型(二)_動力節點Java學院整理

(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描述的是被引用的字段的名稱和描述符。 我們在前面的博客中也提到過, constant_nameandtype_info可以作為字段符號引用的一部分。

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

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

?
1
2
3
4
5
6
7
package com.bjpowernode.test;
public class testint {
 int a = 10;
 void print(){
  system.out.println(a);
 }
}

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

?
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
constant pool:
 #1 = class    #2    // com/bjpowernode/test/testint
 #2 = utf8    com/bjpowernode/test/testint
 ......
 #5 = utf8    a
 #6 = utf8    i
 ......
 #12 = fieldref   #1.#13   // com/bjpowernode/test/testint.a:i
 #13 = nameandtype  #5:#6   // a:i
 ......
{
 void print();
 flags:
 code:
  stack=2, locals=1, args_size=1
   0: getstatic  #19     // field java/lang/system.out:ljava/io/printstream;
   3: aload_0
   4: getfield  #12     // field a:i
   7: invokevirtual #25     // method java/io/printstream.println:(i)v
  10: 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/bjpowernode/test/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 。 

Java class文件格式之數據類型(二)_動力節點Java學院整理

(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描述的是被引用的方法的名稱和描述符。 我們在前面的博客中也提到過, constant_nameandtype_info可以作為方法符號引用的一部分。

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

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

?
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
package com.bjpowernode.test;
public class programer {
 computer computer;
 public programer(computer computer){
  this.computer = computer;
 }
 public void dowork(){
  computer.calculate();
 }
}
package com.bjpowernode.test;
public class computer {
 public void calculate() {
  system.out.println("working...");
 }
}

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

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

?
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
constant pool:
.....
 #12 = utf8    ()v
 #20 = methodref   #21.#23  // com/bjpowernode/test/computer.calculate:()v
 #21 = class    #22   // com/bjpowernode/test/computer
 #22 = utf8    com/bjpowernode/test/computer
 #23 = nameandtype  #24:#12  // calculate:()v
 #24 = utf8    calculate
{
 com.bjpowernode.test.computer computer; 
 flags:
......
 public void dowork();
 flags: acc_public
 code:
  stack=1, locals=1, args_size=1
   0: aload_0
   1: getfield  #13     // field computer:lcom/bjpowernode/test/computer;
   4: invokevirtual #20     // method com/bjpowernode/test/computer.calculate:()v
   7: 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/bjpowernode/test/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 。 

Java class文件格式之數據類型(二)_動力節點Java學院整理

(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描述的是被引用的方法的名稱和描述符。 我們在前面的博客中也提到過, constant_nameandtype_info可以作為方法符號引用的一部分。

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

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

?
1
2
3
4
5
6
7
8
9
10
11
package com.bjpowernode.test;
public class plane {
 iflyable flyable;
 void flytosky(){
  flyable.fly();
 }
}
package com.bjpowernode.test;
public interface iflyable {
 void fly();
}

在上面的代碼中, 定義可一個類plane, 在這個類中有一個iflyable接口類型的字段flyable, 然后在plane的flytosky方法中調用了iflyable中的fly方法。 這就是源代碼中對一個接口中的方法的引用方式, 下面我們反編譯plane, 看看在class文件層面, 對一個接口中的方法的引用是如何描述的。

下面給出反編譯結果, 為了簡潔期間, 省略了一些不相關的內容:

?
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
constant pool:
......
 #8 = utf8    ()v
 #19 = interfacemethodref #20.#22  // com/bjpowernode/test/iflyable.fly:()v
 #20 = class    #21   // com/bjpowernode/test/iflyable
 #21 = utf8    com/bjpowernode/test/iflyable
 #22 = nameandtype  #23:#8   // fly:()v
 #23 = utf8    fly
{
.......
 com.bjpowernode.test.iflyable flyable;
 flags:
.......
 void flytosky();
 flags:
 code:
  stack=1, locals=1, args_size=1
   0: aload_0
   1: getfield  #17     // field flyable:lcom/bjpowernode/test/iflyable;
   4: invokeinterface #19, 1   // interfacemethod com/bjpowernode/test/iflyable.fly:()v
   9: 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/bjpowernode/test/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 。 

Java class文件格式之數據類型(二)_動力節點Java學院整理

總結

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

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

延伸 · 閱讀

精彩推薦
主站蜘蛛池模板: 96日本xxxxxxxxx70 95在线观看精品视频 | 欧美成黑人性猛交xxoo | 久久毛片网站 | 性xxxxⅹhd成人 | 日韩欧美在线看 | 亚洲国产第一区二区三区 | 波多野结在线观看 | 美女光屁股网站 | 天堂资源在线www中文 | 色欲都市| 舔到喷水| 91超级碰| 日韩免费高清完整版 | 9久热久爱免费精品视频在线观看 | 日韩影院在线 | sihu国产午夜精品一区二区三区 | 亚洲色图欧美图片 | 国色天香社区在线 | 欧美一区欧美二区 | 日本xxxx19 | 久久精品手机观看 | 含羞草传媒每天免费一次破解 | 性派对videofreeparty | 99热在线只有精品 | 香蕉久久一区二区不卡无毒影院 | 国产一卡二卡3卡4卡四卡在线视频 | 日韩免费毛片视频杨思敏 | 亚洲国产无线码在线观看 | 男女性gif抽搐出入视频 | 福利片成人午夜在线 | 亚洲国产在线综合018 | 国产精品不卡高清在线观看 | 四虎影院精品 | 9 1 视频在线 | 成年人在线观看免费视频 | 妹妹骑上来蹭着蹭着就射了 | 果冻传媒ⅹxxxxxhd | 50度灰破解版v5.7.0 | 久久精品热在线观看85 | 女人狂吮男人命根gif视频 | 天天操天天干天天做 |