1. 程式人生 > >jvm探祕五:Class類檔案結構之屬性表

jvm探祕五:Class類檔案結構之屬性表

概述

在Class檔案、欄位表和方法表都可以攜帶自己的屬性資訊,這個資訊用屬性表進行描述,用於描述某些場景專有的資訊。

與Class檔案中其它資料項對長度、順序、格式的嚴格要求不同,屬性表集合不要求其中包含的屬性表具有嚴格的順序,並且只要屬性的名稱不與已有的屬性名稱重複,任何人實現的編譯器可以向屬性表中寫入自己定義的屬性資訊。虛擬機器在執行時會忽略不能識別的屬性,為了能正確解析Class檔案,虛擬機器規範中預定義了虛擬機器實現必須能夠識別的9項屬性(預定義屬性已經增加到21項)

  • 常見的屬性
屬性名稱 使用位置 含義
Code 方法表 Java程式碼編譯成的位元組碼指令
ConstantValue 欄位表 final關鍵字定義的常量值
Deprecated 類檔案、欄位表、方法表 被宣告為deprecated的方法和欄位
Exceptions 方法表 方法丟擲的異常
InnerClasses 類檔案 內部類列表
LineNumberTale Code屬性 Java原始碼的行號與位元組碼指令的對應關係
LocalVariableTable Code屬性 方法的區域性變數描述
SourceFile 類檔案 原始檔名稱
Synthetic 類檔案、方法表、欄位表 標識方法或欄位是由編譯器自動生成的

對於每個屬性,它的名稱需要從常量池中引用一個CONSTANT_utf8_info型別的常量類表示,而屬性值的結構則是完全自定義的,只需要通過一個u4的長度屬性區說明屬性值所佔用的位數即可.

  • 屬性表定義的結構
型別 名稱 數量
u2 attribute_name_index 1
u2 attribute_length 1
u1 info attribute_length

一:Code屬性

java程式方法體中的程式碼經過javac編譯器處理後,最終變為位元組碼指令儲存在Code屬性內。Code屬性出現在方法表的屬性集合中,抽象類和介面不存在code屬性。
code屬性是class類檔案中最重要的屬性。class檔案可以分為程式碼(code,方法體裡面的Java程式碼)和元資料(Metadata,包括類,欄位,方法定義及其他資訊)兩部分,code屬性描述程式碼,其他資料項都用於描述元資料。

  • code屬性表結構
型別 名稱 數量
u2 attribute_name_index 1
u4 attribute_length 1
u2 max_stack 1
u2 max_locals 1
u4 code_length 1
u1 code code_length
u2 exception_table_length 1
exception_info exception_table exception_length
u2 attributes_count 1
attribute_info attributes attributes_count
  • Class類檔案中對應的code屬性程式碼

這裡寫圖片描述

  • attribute_name_index

指向CONSTANT_Utf8_info型常量的索引,常量值規定為”Code“,代表了該屬性的屬性名稱。測試用例中值為0x0009,為常量池中的第九項。

#9 = Utf8               Code
  • attribute_length

屬性值的長度,用8個位元組表示,測試用例中值為:0x00000006表示Code屬性值的位元組長度為47。
這裡寫圖片描述

  • max_stack

所需運算元棧的深度的最大值,方法執行的任何時刻,運算元棧都不會超過這個深度。虛擬機器執行時需要根據這個值分配棧幀。
測試用例中為:0x0001,說明需要的最大深度為1,沒有遞迴。

  • max_locals
    代表區域性變量表所需的儲存空間,單位為Slot(插槽),Slot是虛擬機器為區域性變數分配記憶體空間使用的最小單位。長度不超過32位的資料型別佔用1個Slot(byte,char,float,int,short,boolean,returnAddress),64位的資料型別(long和double)佔用2個Slot。Slot可以重用。當代碼執行超過區域性變數的作用域時,Solt可以被其他區域性變數使用。
    測試用例中為:0x0001,說明需要的區域性變數槽位為1
  • code_length和code

這兩個用來儲存java源程式編譯後生成的位元組碼指令。code_lenth代表位元組碼長度(u4),code用於儲存位元組碼指令的一系列位元組流。每個位元組指令是一個u1資料型別(1bit).虛擬機器讀取到一個一個位元組碼時,就可以找出對應的這個位元組碼是什麼指令。java虛擬機器最多可以有256條指令,現在有200多條指令。
這裡寫圖片描述
位元組碼區域長度為0x00000005,虛擬機器讀取到後會順序依次的讀取之後的5個位元組,並根據位元組碼指令表翻譯為對應的位元組碼指令。
過程為
1:讀入2A,對應指令為aload_0,將低0個Slot槽位為reference型別的本地變數推送到棧的頂端。
2:讀入B7,對應指令為invokespecial,將棧頂的reference型別的資料所指向的物件作為方法的接收者,呼叫此物件的例項構造方法。這條指令帶有一個u2型別的引數,為具體呼叫的哪一個方法,指向常量池中一個
CONSTANT_Methodref_info型別常量,即此方法的符號應用。
3:讀入00 0A,0x000A對應為常量池第10個常量,為例項構造器init方法的符號引用

  #10 = Methodref          #3.#11         // java/lang/Object."<init>":()V

讀入B1,對應指令為return,含義為返回此方法,返回值為void。這條指令執行完後當前方法結束。
屬性表對應的方法表完整程式碼

{
  public cn.yuli.jvm.TestClass();
    descriptor: ()V
    flags: ACC_PUBLIC
    Code:
      stack=1, locals=1, args_size=1
         0: aload_0
         1: invokespecial #10                 // Method java/lang/Object."<init>":()V
         4: return
      LineNumberTable:
        line 3: 0
      LocalVariableTable:
        Start  Length  Slot  Name   Signature
            0       5     0  this   Lcn/yuli/jvm/TestClass;

  public int inc();
    descriptor: ()I
    flags: ACC_PUBLIC
    Code:
      stack=2, locals=1, args_size=1
         0: aload_0
         1: getfield      #18                 // Field m:I
         4: iconst_1
         5: iadd
         6: ireturn
      LineNumberTable:
        line 6: 0
      LocalVariableTable:
        Start  Length  Slot  Name   Signature
            0       7     0  this   Lcn/yuli/jvm/TestClass;
}

這兩個為例項構造器方法init()和inc(),locals和Args_size=1是應為有this引用,區域性變數第一槽位儲存的是本物件的this引用,如果方法定義為static,locals就為0了。

  • exception_table_length和exception_info

exception_table_length是u2型別,4個位元組。異常表對Code屬性來說不是必須存在, 在本例項中為0x0000,說明不存在異常表。

  • attributes_count和attributes

為Code表中包含的其他屬性,如:
LineNumberTable屬性,用於描述java原始碼行號和位元組碼行號之間的對應關係。
LocalVariableTable屬性,使用者描述棧中區域性變量表中的變數和java原始碼中定義的變數的關係。
繼續讀位元組碼檔案,0x0000之後是0x0002,說明Code錶帶有兩個屬性。第一個屬性是0x000C,轉換為10進製為12查常量表為

 #12 = Utf8               LineNumberTable

說明是LineNumberTable屬性,根據LineNumberTable屬性結構,接下來為u4型別的長度描,0x0000006,為6位bit。
接下來2位為0x0001,即該line_number_table中只有一個line_number_info表,位元組碼行號start_pc為0x0000,l原始碼行號ine_number為0x0006,LineNumberTable屬性結束。

相關推薦

jvm探祕Class檔案結構屬性

概述 在Class檔案、欄位表和方法表都可以攜帶自己的屬性資訊,這個資訊用屬性表進行描述,用於描述某些場景專有的資訊。 與Class檔案中其它資料項對長度、順序、格式的嚴格要求不同,屬性表集合不要求其中包含的屬性表具有嚴格的順序,並且只要屬性的名稱不與已

深入理解JVM虛擬機器(四)Class檔案結構(二)

屬性表在前面的講解中出現多次,在Class檔案、欄位表、方法表都可以攜帶自己的屬性表集合,用於描敘某些場景專有的資訊。為了正確解析Class檔案,《Java虛擬機器規範(第二版)》中預定義了9項虛擬機器實現應當識別的屬性。然而在最新的《Java虛擬機器規範(Java SE7)》中屬性表已經增

【深入Java虛擬機器】Class檔案結構

平臺無關性     Java是與平臺無關的語言,這得益於Java原始碼編譯後生成的儲存位元組碼的檔案,即Class檔案,以及Java虛擬機器的實現。不僅使用Java編譯器可以把Java程式碼編譯成儲存位元組碼的Class檔案,使用JRuby等其他語言的編譯器也可以把程式

Class檔案結構ConstantValue屬性

程式設計過程中經常用的static,final關鍵字,也經常聽到同事談起這些詞,到底他們怎麼樣呢,jvm中class類檔案結構可以找到答案。 ConstantValue屬性 ConstantValue屬性的作用是通知虛擬機器自動為靜態變數賦值,只有被stat

JVM虛擬機器 - Class檔案結構

JVM虛擬機器 - Class類檔案結構 概述 Class檔案是一組以8位位元組為基礎單位的二進位制流,各個資料專案嚴格按照順序緊湊地排列在Class檔案之中,中間沒有新增任何分隔符,這使得整個Class檔案中儲存的內容幾乎都是程式執行的必要資料。當遇到需要佔用8位位元組以上空間的資

如何學好JVM征服面試官?一篇Class 檔案結構你還不會嗎?

        Java 跨平臺的基礎 各種不同平臺的虛擬機器與所有平臺都

Java Class檔案結構

平臺無關性 Java是與平臺無關的語言,這得益於Java原始碼編譯後生成的儲存位元組碼的檔案,即Class檔案,以及Java虛擬機器的實現。不僅使用Java編譯器可以把Java程式碼編譯成儲存位元組碼的Class檔案,使用JRuby等其他語言的編譯器也可以把程式程式碼編譯成Class檔案,虛擬機

Class 檔案結構

> 本文部分摘自《深入理解 Java 虛擬機器第三版》 ## 概述 我們知道,Java 具有跨平臺性,其實現基礎就是虛擬機器和位元組碼儲存格式。Java 虛擬機器不與 Java 語言繫結,只與 Class 檔案所關聯。Java 虛擬機器作為一個通用的、與機器無關的執行平臺,任何語言都可以將 Jav

深入理解JVM檔案結構

今天我們來介紹一下Class類檔案結構 1.概述 計算機雖然只能識別0和1,但是越來越多的程式語言選擇了與作業系統和機器指令集無關的、平臺中立的格式作為程式編譯後的儲存格式。Java虛擬機器不和包括Java在內的任何語言繫結,只與“class檔案”這種特定的二進

深入理解JVM檔案結構

前言 我們平時在DOS介面中往往需要執行先執行javac命令,這個命令的直接結果就是產生相應的class檔案,然後基於這個class檔案才可以真正執行程式得到結果。自然。這是Java虛擬機器的功勞,那麼是不是Java虛擬機器只能編譯.java的原始檔呢?答案是

JVMclass檔案結構

作為Java程式猿,我們知道,我們寫好的.java 原始碼,最後會被Java編譯器編譯成字尾為.class的檔案,該型別的檔案是由位元組組成的檔案,又叫位元組碼檔案。那麼,class位元組碼檔案裡面到底是有什麼呢?它又是怎樣組織的呢?讓我們先來大概瞭解一下他的組成結構吧。  

深入理解JVM虛擬機器(三)檔案結構(上)

前言 在上一篇深入理解JVM虛擬機器:(二)垃圾收集器概述 文章中,我們瞭解了Java虛擬機器中垃圾收集器的種類以及垃圾回收的方式等,這一篇,我們將去了解一下Java中類檔案的內部構造,由於這一章比較抽象,因此將會分為兩篇文章進行講解。 概述 程式碼編譯的

Java中的檔案結構之一如何分析一個.class檔案的二進位制碼內容

該文為作者原創,請轉載者註明出處 以下為一個Java類--Temp4Test package com.demo; public class Temp4Test extends Temp3Test { private int i = 1;

【搞定Jvm面試】 面試官談談 JVM 檔案結構的認識

類檔案結構 一 概述 在 Java 中,JVM 可以理解的程式碼就叫做位元組碼(即副檔名為 .class 的檔案),它不面向任何特定的處理器,只面向虛擬機器。Java 語言通過位元組碼的方式,在一定程度上解決了傳統解釋型語言執行效率低的問題,同時又保留了解釋型語言可移植的特點。所以 Java 程式執行時比較高

【深入Java虛擬機】Class文件結構

本質 拒絕 處理 implement align 默認值 改變 占用 至少 平臺無關性 Java是與平臺無關的語言,這得益於Java源代碼編譯後生成的存儲字節碼的文件,即Class文件,以及Java虛擬機的實現。不僅使用Java編譯器可以把Java代碼編譯成存儲字節

「深入Java虛擬機(2)」Class文件結構

1.5 trac 三種 type 類構造 face 方法 class throw Java是與平臺無關的語言,這得益於Java源代碼編譯後生成的存儲字節碼的文件,即Class文件,以及Java虛擬機的實現。不僅使用Java編譯器可以把Java代碼編譯成存儲字節碼的Class

JVM系列第5講位元組碼檔案結構

溫馨提示:此篇文章長達兩萬字,圖片50多張,內容非常多,建議收藏後再看。 前面我們說到 Java 虛擬機器使用位元組碼實現了跨平臺的願景,無論什麼系統,我們都可以使用 Java 虛擬機器解釋執行位元組碼檔案。但其實位元組碼是有一套規範的,而規定位元組碼格式的就是《Java 虛擬機器規範》。《Ja

讀書筆記 ---- 《深入理解Java虛擬機器》---- 第5篇檔案結構

上一篇:虛擬機器效能監控與故障處理工具:https://blog.csdn.net/pcwl1206/article/details/84197113 第5篇:類檔案結構 開篇說明:本文的重點就是類檔案結構,只需要清楚Class檔案格式中的各名稱的實際意義就行,不用對具體名稱下的細節進行深究

深入理解JVM(六)——檔案結構——code

Code Java程式中方法體中的程式碼經過Javac編譯器處理之後,最終變成位元組碼指令儲存在Code屬性內。 Code屬性出現在方法表的屬性集合之中,但不是所有的方法表都必須有,譬如介面或者抽象類。 Code是Class檔案中最重要的一個屬性,如果把一個Java程式中的資訊分

深入理解JVM(六)——檔案結構

Java誕生之初就有的口號,Write Once,Run Anywhere Java規範分為Java語言規範和Java虛擬機器規範,Java實現平臺無關性的基礎是虛擬機器和位元組碼儲存格式,Java虛擬機器不與包括Java在內的任何語言繫結,它只與Class檔案這種特定的二進位制檔案格式