【JVM虛擬機】(7)---深刻理解Class中-屬性集合

<center>深刻理解Class中-屬性集合</center>

以前有關class文件已經寫了兩篇博客:html

一、【JVM虛擬機】(5)---深刻理解JVM-Class中常量池java

二、【JVM虛擬機】(6)---深刻理解Class中訪問標誌、類索引、父類索引、接口索引數組

那麼這篇博客主要講有關 字段表集合 相關的理解和代碼示例。dom

字段表:用於描述接口或者類中聲明的變量,字段包括類級(static修飾)變量以及實例級變量,可是不包括局部變量(方法內部變量)。spa

##<font color=#FFD700>1、概念 </font>3d

字段表集合:包括了字段計數器字段數據區如圖:code

Field_info: 依次包含訪問標誌(access_flags)、名稱索引(name_index)、描述符索引(descriptor_index)、屬性表集合(attributes)幾項。htm

<img src="https://img2018.cnblogs.com/blog/1090617/201904/1090617-20190411231413546-2127494420.png" style="border: 1px dashed rgb(204, 200, 200);" width="600" height="450">對象

字段修飾符放在access_flags項目中,它與類中的access_flags項目是很是類似的,都是一個u2的數據類型.blog

<img src="https://img2018.cnblogs.com/blog/1090617/201904/1090617-20190411231458127-370081870.jpg" style="border: 1px dashed rgb(204, 200, 200);" width="600" height="325">

跟隨access_flags標誌的是兩項索引值:name_indexdescriptor_index,它們都是對常量池的引用,分別表明着字段的簡單名稱以及字段方法和方法的描述符

描述符的做用:是用來描述字段的數據類型,方法的參數列表(包括數量,類型以及順序)和返回值。

描述符規則: 基本數據類型以及表明無返回值的void類型都用一個大寫字符來表示,而對象類型則用字符加L加對象名的全限定名來表示:

<img src="https://img2018.cnblogs.com/blog/1090617/201904/1090617-20190411231525191-1906804832.jpg" style="border: 1px dashed rgb(204, 200, 200);" width="600" height="400">

數組類型:每一維度將使用一個前置的"["字符來描述.如一個定義爲"java.lang.Stirng[ ]"類型的二維數組,將被記錄爲:"[[Ljava/lang/Stirng",一個整型數組"int[]"將被記錄爲"[I".

用描述符來描述方法: 按照先參數列表,後返回值的順序來描述,參數列表按照參數的嚴格順序放在一組小括號"()"以內。

字段表集合中不會列出從父類或者父接口中繼承而來的字段。 <br>

##<font color=#FFD700> 2、屬性表集合-----靜態field字段的初始化 </font>

在定義**屬性字段**的過程當中,咱們有時候會很天然地對 屬性字段 直接賦值,以下所示:

public static final int MAX=100;  
public  int count=0;

對於虛擬機而言,上述的兩個**屬性字段**賦值的時機是不一樣的:

  • 對於非靜態(即無static修飾)的屬性字段的賦值將會出如今實例構造方法**<init>()**中

  • 對於靜態的屬性字段,有兩個選擇:一、在靜態構造方法**<cinit>()中進行;2 、使用ConstantValue**屬性進行賦值。

Sun javac編譯器對於 靜態屬性字段 的初始化賦值策略

1)、若是使用finalstatic同時修飾一個屬性字段,而且這個字段是基本類型或者String類型的,那麼編譯器在編譯這個字段的時候,會在對應的field_info結構體中 增長一個ConstantValue類型的結構體,在賦值的時候使用這個ConstantValue進行賦值。

2)、若是該屬性字段並無被final修飾,或者不是基本類型或者String類型,那麼將在類構造方法**<cinit>()**中賦值。

對於上述的public static final init MAX=100; javac編譯器在編譯此屬性字段構建field_info結構體時,除了訪問標誌、名稱索引、描述符索引外,會增長一個**ConstantValue**類型的屬性表。

<img src="https://img2018.cnblogs.com/blog/1090617/201904/1090617-20190411231712680-1015512537.jpg" style="border: 1px dashed rgb(204, 200, 200);" width="580" height="450">

<br>

<font color=#FFD700>3、示例 </font>

####一、先來個網上的例子,圖片解釋很好

public class Simple {  
    private  transient static final String str ="This is a test";  
}

<img src="https://img2018.cnblogs.com/blog/1090617/201904/1090617-20190411231724787-940812686.jpg" style="border: 1px dashed rgb(204, 200, 200);" width="662" height="821">

說明

一、字段計數器中的值爲0x0001,表示這個類就定義了一個屬性字段

二、 字段的訪問標誌0x009A,這個字段的標誌符有:ACC_TRANSIENT、ACC_FINAL、ACC_STATIC、ACC_PRIVATE;

三、 名稱索引中的值爲0x0005,指向了常量池中的第5項,爲「str」,代表這個屬性字段的名稱是str

四、描述索引中的值爲0x0006,指向了常量池中的第6項,爲"Ljava/lang/String;",代表這個field字段的數據類型是java.lang.String類型;

五、屬性表計數器中的值爲0x0001,代表field_info還有一個屬性表;

六、屬性表名稱索引中的值爲0x0007**,指向常量池中的第7項,爲「ConstantValue」,代表這個屬性表的名稱是ConstantValue**,即屬性表的類型是ConstantValue類型的;

七、屬性長度中的值爲0x0002,由於此屬性表是ConstantValue類型,它的值固定爲2

八、常量值索引 中的值爲0x0008,指向了常量池中的第8項,爲CONSTANT_String_info類型的項,表示「This is a test」 的常量。在對此field賦值時,會使用此常量對field賦值。

####二、自測

package com.jincou.demo.domain;

public class XiaoXiao {
    public String name = "小小";
    private Integer age = 3;
    public static final String sex = "女";
}

接下來看16進制文件和class反編譯文件

//一、這裏直接截取到訪問標誌服後的16進制數據,從|開始表明字段集合相關16進制
                                     00
2100 0600 0700 00|00 0300 0100 0800 0900
0000 0200 0a00 0b00 0000 1900 0c00 0900
0100 0d00 0000 0200 0e00 0100 0100 0f00
1000 0100 1100 0000 3300 0200 0100 0000
132a b700 012a 1202 b500 032a 06b8 0004
b500 05b1 0000 0001 0012 0000 000e 0003
0000 0003 0004 0004 000a 0005 0001 0013
0000 0002 0014 
                                       
//二、查看 XiaoXiao.class反編譯數據信息
Constant pool:
   #1 = Methodref          #7.#21         // java/lang/Object."<init>":()V
   #2 = String             #22            // 小小
   #3 = Fieldref           #6.#23         // com/jincou/demo/domain/XiaoXiao.name:Ljava/lang/String;
   #4 = Methodref          #24.#25        // java/lang/Integer.valueOf:(I)Ljava/lang/Integer;
   #5 = Fieldref           #6.#26         // com/jincou/demo/domain/XiaoXiao.age:Ljava/lang/Integer;
   #6 = Class              #27            // com/jincou/demo/domain/XiaoXiao
   #7 = Class              #28            // java/lang/Object
   #8 = Utf8               name
   #9 = Utf8               Ljava/lang/String;
  #10 = Utf8               age
  #11 = Utf8               Ljava/lang/Integer;
  #12 = Utf8               sex
  #13 = Utf8               ConstantValue
  #14 = String             #29            // 女
  #15 = Utf8               <init>
  #16 = Utf8               ()V
  #17 = Utf8               Code
  #18 = Utf8               LineNumberTable
  #19 = Utf8               SourceFile
  #20 = Utf8               XiaoXiao.java
  #21 = NameAndType        #15:#16        // "<init>":()V
  #22 = Utf8               小小
  #23 = NameAndType        #8:#9          // name:Ljava/lang/String;
  #24 = Class              #30            // java/lang/Integer
  #25 = NameAndType        #31:#32        // valueOf:(I)Ljava/lang/Integer;
  #26 = NameAndType        #10:#11        // age:Ljava/lang/Integer;
  #27 = Utf8               com/jincou/demo/domain/XiaoXiao
  #28 = Utf8               java/lang/Object
  #29 = Utf8               女
  #30 = Utf8               java/lang/Integer
  #31 = Utf8               valueOf
  #32 = Utf8               (I)Ljava/lang/Integer;

接下來咱們來分析從00 03開始。

//00 03 表明示成員變量的個數,此處爲3個。
1)00 01 結合上表表明第一個變量的修飾符爲 public
2)00 08 找常量池第8個 name
3)00 09 找常量池第9個 String
4)00 00 用來描述該變量的屬性,由於這個變量沒有附加屬性,因此attributes_count爲0,attribute_info爲空。
 //接下來直接分析第三個
1)00 19 結合上表 ACC_PUBLIC+ACC_STATIC+ACC_FINAL 恰好19
2)00 0c 找常量池第12個 sex
3)00 09 找常量池第9個 String
4)00 01 表明這個變量有一個附加屬性
5)00 0d 找常量池第13個 ConstantValue
6)00 0000 02 屬性長度
7)00 0e 找常量池第14個 女

經過這個例子咱們注意到: 1)、name = "小小"中的小小並無出現,這就是上一個例子所說的,由於它不是靜態變量因此不屬於類,而是屬於對象,因此在建立對象的時候,纔會出現。 2)、sex = "女" 中的出現了,由於它是靜態屬性字段,屬於類級別的因此出現。

<font color=#FFD700>參考 </font>

一、深刻了解java虛擬機第2版第六章

二、深刻理解JVM-Class文件屬性集合

<br> <br>

只要本身變優秀了,其餘的事情纔會跟着好起來(少將5)

原文出處:https://www.cnblogs.com/qdhxhz/p/10693324.html

相關文章
相關標籤/搜索