欧美bbbwbbbw肥妇,免费乱码人妻系列日韩,一级黄片

Java class文件格式之屬性詳解_動(dòng)力節(jié)點(diǎn)java學(xué)院整理

 更新時(shí)間:2017年06月14日 14:06:36   投稿:mrr  
這篇文章主要介紹了Java class文件格式之屬性詳解,需要的朋友可以參考下

Code屬性

code屬性是方法的一個(gè)最重要的屬性。 因?yàn)樗锩娲娣诺氖欠椒ǖ淖止?jié)碼指令, 除此之外還存放了和操作數(shù)棧,局部變量相關(guān)的信息。 所有不是抽象的方法, 都必須在method_info中的attributes中有一個(gè)Code屬性。下面是Code屬性的結(jié)構(gòu), 為了更直觀的展示Code屬性和method_info的包含關(guān)系, 特意畫(huà)出了method_info:

下面依次介紹code屬性中的各個(gè)部分。

attribute_name_index指向常量池中的一個(gè)CONSTANT_Utf8_info , 這個(gè)CONSTANT_Utf8_info 中存放的是當(dāng)前屬性的名字 “Code” 。

attribute_length給出了當(dāng)前Code屬性的長(zhǎng)度(不包括前六字節(jié))。

max_stack 指定當(dāng)前方法被執(zhí)行引擎執(zhí)行的時(shí)候, 在棧幀中需要分配的操作數(shù)棧的大小。

max_locals指定當(dāng)前方法被執(zhí)行引擎執(zhí)行的時(shí)候, 在棧幀中需要分配的局部表量表的大小。注意, 這個(gè)數(shù)字并不是局部變量的個(gè)數(shù), 因?yàn)楦鶕?jù)局部變量的作用域不同, 在執(zhí)行到一個(gè)局部變量以外時(shí), 下一個(gè)局部變量可以重用上一個(gè)局部變量的空間(每個(gè)局部變量在局部變量表中占用一個(gè)或兩個(gè)Slot)。 方法中的局部變量包括方法的參數(shù), 方法的默認(rèn)參數(shù)this, 方法體中定義的變量, catch語(yǔ)句中的異常對(duì)象。 關(guān)于執(zhí)行引擎的相關(guān)內(nèi)容會(huì)在后面的博客中講到。

code_length指定該方法的字節(jié)碼的長(zhǎng)度, class文件中每條字節(jié)碼占一個(gè)字節(jié)。

code存放字節(jié)碼指令本身, 它的長(zhǎng)度是code_length個(gè)字節(jié)。

exception_table_length 指定異常表的大小

exception_table就是所謂的異常表, 它是對(duì)方法體中try-catch_finally的描述。 exception_table可以看做是一個(gè)數(shù)組, 每個(gè)數(shù)組項(xiàng)是一個(gè)exception_info結(jié)構(gòu), 一般來(lái)說(shuō)每個(gè)catch塊對(duì)應(yīng)一個(gè)exception_info,編譯器也可能會(huì)為當(dāng)前方法生成一些exception_info。 exception_info的結(jié)構(gòu)如下(為了直觀的顯示exception_info, exception_table和Code屬性的關(guān)系, 畫(huà)出了Code屬性,的話讀者就會(huì)更清楚各個(gè)數(shù)據(jù)項(xiàng)之間的位置關(guān)系和包含關(guān)系):

下面講解exception_info中的各個(gè)字段的意思。

start_pc是從字節(jié)碼(Code屬性中的code部分)起始處到當(dāng)前異常處理器起始處的偏移量。

end_pc是從字節(jié)碼起始處到當(dāng)前異常處理器末尾的偏移量。

handler_pc是指當(dāng)前異常處理器用來(lái)處理異常(即catch塊)的第一條指令相對(duì)于字節(jié)碼開(kāi)始處的偏移量。

catch_type是一個(gè)常量池索引, 指向常量池中的一個(gè)CONSTANT_Class_info數(shù)據(jù)項(xiàng), 該數(shù)據(jù)項(xiàng)描述了catch塊中的異常的類型信息。這個(gè)類型必須是java.lang.Throwable的或其子類。

所以可以總結(jié), 一個(gè)異常處理器(exception_info)的意思是: 如果偏移量從start_pc到end_pc之間的字節(jié)碼出現(xiàn)了catch_type描述的類型的異常, 那么就跳轉(zhuǎn)到偏移量為handler_pc的字節(jié)碼處去執(zhí)行。如果catch_type為0, 就代表不引用任何常量池項(xiàng)(再回顧一下, 常量池中的項(xiàng)是從1開(kāi)始計(jì)的), 那么這個(gè)exception_info用于實(shí)現(xiàn)finally子句。

我們一直在介紹Code屬性, 只不過(guò)剛才進(jìn)行了一個(gè)小插曲, 介紹了Code屬性中的exception_table中的exception_info的詳細(xì)信息。 下面我們繼續(xù)介紹Code 屬性中的其他信息, 希望讀者不要被繞暈了 : )

attributes_count 表示當(dāng)前Code 屬性中存在的其他屬性的個(gè)數(shù)。 現(xiàn)在我們知道, class中的屬性, 不僅會(huì)出現(xiàn)在頂層的class中, 會(huì)存在field_info中, 會(huì)存在method_info中, 甚至還會(huì)出現(xiàn)在屬性中。 

attributes可以看做是一個(gè)數(shù)組, 里面存放了Code屬性中的其他屬性。 Code 屬性中可以出現(xiàn)的其他屬性有LineNumberTable和LocalVariableTable 。 這兩個(gè)屬性會(huì)在下面介紹。

LineNumberTable屬性

LineNumberTable屬性存在于Code屬性中, 它建立了字節(jié)碼偏移量到源代碼行號(hào)之間的聯(lián)系。 這個(gè)屬性是可選的, 編譯器可以選擇不生成該屬性。下面是該屬性的結(jié)構(gòu)(同樣給出了全局的位置關(guān)系,LineNumberTable在圖的右下角部分):

由于這個(gè)屬性并不是重點(diǎn), 我們?cè)诖撕?jiǎn)單的講述。 

每個(gè)LineNumberTable中的line_number_table部分, 可以看做是一個(gè)數(shù)組, 數(shù)組的每項(xiàng)是一個(gè)line_number_info , 每個(gè)line_number_info 結(jié)構(gòu)描述了一條字節(jié)碼和源碼行號(hào)的對(duì)應(yīng)關(guān)系。 其中start_pc是這個(gè)line_number_info 描述的字節(jié)碼指令的偏移量, line_number是這個(gè)line_number_info 描述的字節(jié)碼指令對(duì)應(yīng)的源碼中的行號(hào)。可以看出, 方法中的每條字節(jié)碼都對(duì)應(yīng)一個(gè)line_number_info , 這些line_number_info 中的line_number可以指向相同的行號(hào), 因?yàn)橐恍性创a可以編譯出多條字節(jié)碼。

LocalVariableTable屬性 

LocalVariableTable 屬性建立了方法中的局部變量與源代碼中的局部變量之間的對(duì)應(yīng)關(guān)系。 這個(gè)屬性存在于Code屬性中。 這個(gè)屬性是可選的, 編譯器可以選擇不生成這個(gè)屬性。該屬性的結(jié)構(gòu)如下:(同樣給出了全局的位置關(guān)系圖,LocalVariableTable 在該圖的右下角 )

由于這個(gè)屬性相對(duì)不那么重要, 這里只是大概講解一下。

每個(gè)LocalVariableTable 的local_variable_table部分可以看做是一個(gè)數(shù)組, 每個(gè)數(shù)組項(xiàng)是一個(gè)叫做local_variable_info的結(jié)構(gòu), 該結(jié)構(gòu)描述了某個(gè)局部變量的變量名和描述符, 還有和源代碼的對(duì)應(yīng)關(guān)系。下面講解local_variable_info的各個(gè)部分:

start_pc是當(dāng)前l(fā)ocal_variable_info所對(duì)應(yīng)的局部變量的作用域的起始字節(jié)碼偏移量;

length是當(dāng)前l(fā)ocal_variable_info所對(duì)應(yīng)的局部變量的作用域的大小。 也就是從字節(jié)碼偏移量start_pc 到start_pc+length就是當(dāng)前局部變量的作用域范圍;

name_index指向常量池中的一個(gè)CONSTANT_Utf8_info, 該CONSTANT_Utf8_info描述了當(dāng)前局部變量的變量名;

descriptor_index指向常量池中的一個(gè)CONSTANT_Utf8_info, 該CONSTANT_Utf8_info描述了當(dāng)前局部變量的描述符;

index描述了在該方法被執(zhí)行時(shí),當(dāng)前局部變量在棧幀中局部變量表中的位置。 

由此可知, 方法中的每個(gè)局部變量都會(huì)對(duì)應(yīng)一個(gè)local_variable_info 。 

Exceptions屬性

首先需要說(shuō)明, Exceptions屬性不是存在于Code屬性中的, 它存在于method_info中的attributes中。 和Code屬性是平級(jí)的。 這個(gè)屬性描述的是方法聲明的可能會(huì)拋出的異常, 也就是方法定義后面的throws聲明的異常列表, 請(qǐng)不要和上面提到的異常處理器混淆。 異常處理器描述了方法的字節(jié)碼如何處理異常, 而Exceptions屬性描述方法可能會(huì)拋出哪些以異常。下面講解Exceptions屬性的結(jié)構(gòu)(左下角為Exceptions屬性):

下面講解Exceptions屬性中的信息。 

attribute_name_index和attribute_length就不多說(shuō)了, 和其他屬性是一樣的。 

number_of_exceptions是該方法要拋出的異常的個(gè)數(shù)。 

exceptions_index_table可以看做一個(gè)數(shù)組, 這個(gè)數(shù)組中的每一項(xiàng)占兩個(gè)字節(jié), 這兩個(gè)字節(jié)是對(duì)常量池的索引, 它指向一個(gè)常量池中的CONSTANT_Class_info。 這個(gè)CONSTANT_Class_info描述了一個(gè)被拋出的異常的類型。 

總結(jié)

到此為止, 和方法相關(guān)的屬性就介紹完了。 這篇博客講解的內(nèi)容相對(duì)比較復(fù)雜。 下面以一個(gè)實(shí)例進(jìn)行驗(yàn)證, 實(shí)例代碼:

package com.bjpowernode.test; 
public class Test { 
  public void test() throws Exception{ 
    int localVar = 0; 
    try{ 
      Class.forName("com.bjpowernode.test.Person"); 
    }catch(ClassNotFoundException e){ 
      throw e; 
    }finally{ 
      System.out.println(localVar); 
    } 
  } 
}

反編譯后的test方法部分(省略了常量池等信息):

public void test() throws java.lang.Exception; 
 flags: ACC_PUBLIC 
 Exceptions: 
  throws java.lang.Exception 
 Code: 
  stack=2, locals=4, args_size=1 
    0: iconst_0 
    1: istore_1 
    2: ldc      #18         // String com.bjpowernode.test.Person 
    4: invokestatic #20         // Method java/lang/Class.forName:(Ljava/lang/String;)Ljava/lang/Class; 
    7: pop 
    8: goto     24 
   11: astore_2 
   12: aload_2 
   13: athrow 
   14: astore_3 
   15: getstatic   #26         // Field java/lang/System.out:Ljava/io/PrintStream; 
   18: iload_1 
   19: invokevirtual #32         // Method java/io/PrintStream.println:(I)V 
   22: aload_3 
   23: athrow 
   24: getstatic   #26         // Field java/lang/System.out:Ljava/io/PrintStream; 
   27: iload_1 
   28: invokevirtual #32         // Method java/io/PrintStream.println:(I)V 
   31: return 
  Exception table: 
    from  to target type 
      2   8  11  Class java/lang/ClassNotFoundException 
      2  14  14  any 
  LineNumberTable: 
   line 7: 0 
   line 11: 2 
   line 13: 8 
   line 15: 12 
   line 16: 14 
   line 17: 15 
   line 18: 22 
   line 17: 24 
   line 20: 31 
  LocalVariableTable: 
   Start Length Slot Name  Signature 
       0   32   0 this  Lcom/bjpowernode/test/Test; 
       2   30   1 localVar  I 
      12    2   2   e  Ljava/lang/ClassNotFoundException; 

結(jié)合上面的講解和圖解, 再分析反編譯的結(jié)果, 就一目了然了: 所有的結(jié)果是一個(gè)method_info, method_info開(kāi)始處是訪問(wèn)標(biāo)志信息。 然后是method_info的 Exceptions屬性 , Exceptions屬性屬性下面是Code屬性, Code屬性中又包括字節(jié)碼, 異常處理器 ,LineNumberTable屬性和LocalVariableTable 屬性。 

所以會(huì)直接或間接的和method_info有聯(lián)系, 最后給出一張全局圖, 這樣的話, 讀者就比較明確, 一個(gè)完整的方法, 是如何在class文件中描述的,由于考慮到復(fù)雜性, 這些屬性或其他數(shù)據(jù)項(xiàng)中, 對(duì)常量池的引用均未畫(huà)出:

相關(guān)文章

  • Java服務(wù)器端跨域問(wèn)題解決方案

    Java服務(wù)器端跨域問(wèn)題解決方案

    這篇文章主要介紹了java服務(wù)器端跨域問(wèn)題解決方案,文中通過(guò)示例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友可以參考下
    2020-01-01
  • Java讀取項(xiàng)目json文件并轉(zhuǎn)為JSON對(duì)象的操作

    Java讀取項(xiàng)目json文件并轉(zhuǎn)為JSON對(duì)象的操作

    這篇文章主要介紹了Java讀取項(xiàng)目json文件并轉(zhuǎn)為JSON對(duì)象的操作,具有很好的參考價(jià)值,希望對(duì)大家有所幫助。如有錯(cuò)誤或未考慮完全的地方,望不吝賜教
    2021-08-08
  • 淺談Springboot2.0防止XSS攻擊的幾種方式

    淺談Springboot2.0防止XSS攻擊的幾種方式

    本文主要介紹了Springboot2.0防止XSS攻擊的幾種方式,文中通過(guò)示例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友們下面隨著小編來(lái)一起學(xué)習(xí)學(xué)習(xí)吧
    2022-08-08
  • 深入理解Java并發(fā)編程之LinkedBlockingQueue隊(duì)列

    深入理解Java并發(fā)編程之LinkedBlockingQueue隊(duì)列

    本文主要介紹了Java并發(fā)編程之LinkedBlockingQueue隊(duì)列,文中通過(guò)示例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友們下面隨著小編來(lái)一起學(xué)習(xí)學(xué)習(xí)吧
    2022-04-04
  • Jmeter參數(shù)化實(shí)現(xiàn)方法及應(yīng)用實(shí)例

    Jmeter參數(shù)化實(shí)現(xiàn)方法及應(yīng)用實(shí)例

    這篇文章主要介紹了Jmeter參數(shù)化實(shí)現(xiàn)方法及應(yīng)用實(shí)例,文中通過(guò)示例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友可以參考下
    2020-08-08
  • Java(TM) Platform SE binary 打開(kāi)jar文件的操作

    Java(TM) Platform SE binary 打開(kāi)jar文件的操作

    這篇文章主要介紹了Java(TM) Platform SE binary 打開(kāi)jar文件的操作,具有很好的參考價(jià)值,希望對(duì)大家有所幫助。一起跟隨小編過(guò)來(lái)看看吧
    2021-02-02
  • 詳解SpringBoot通用配置文件(不定時(shí)更新)

    詳解SpringBoot通用配置文件(不定時(shí)更新)

    這篇文章主要介紹了SpringBoot通用配置文件詳解(不定時(shí)更新),本文通過(guò)實(shí)例代碼給大家介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或工作具有一定的參考借鑒價(jià)值,需要的朋友可以參考下
    2021-03-03
  • Java實(shí)現(xiàn)打印二叉樹(shù)所有路徑的方法

    Java實(shí)現(xiàn)打印二叉樹(shù)所有路徑的方法

    這篇文章主要介紹了Java實(shí)現(xiàn)打印二叉樹(shù)所有路徑的方法,涉及java二叉樹(shù)遍歷與運(yùn)算相關(guān)操作技巧,需要的朋友可以參考下
    2018-02-02
  • 一文掌握J(rèn)avaWeb登錄認(rèn)證

    一文掌握J(rèn)avaWeb登錄認(rèn)證

    登錄認(rèn)證是每個(gè)系統(tǒng)中必不可少的功能,通過(guò)用戶名和密碼來(lái)驗(yàn)證用戶身份,JavaWeb中實(shí)現(xiàn)登錄認(rèn)證通常需要處理HTTP協(xié)議的無(wú)狀態(tài)性,涉及會(huì)話管理、令牌技術(shù)等,本文給大家介紹JavaWeb登錄認(rèn)證的相關(guān)知識(shí),感興趣的朋友跟隨小編一起看看吧
    2024-09-09
  • Java中Dom4j的配置與使用示例詳解

    Java中Dom4j的配置與使用示例詳解

    Dom4j是一個(gè)強(qiáng)大的Java庫(kù),用于處理XML數(shù)據(jù),結(jié)合了DOM、SAX、JDOM的優(yōu)點(diǎn),它可以解析、生成、修改和序列化XML文檔,適用于數(shù)據(jù)交換、配置文件管理、日志記錄、數(shù)據(jù)持久化和Web服務(wù)等場(chǎng)景,Dom4j提供了簡(jiǎn)單易用的API,便于開(kāi)發(fā)者進(jìn)行高效的XML操作
    2024-10-10

最新評(píng)論