java 位元組碼文件詳解

来源:https://www.cnblogs.com/zzlove2018/archive/2018/05/27/9097885.html
-Advertisement-
Play Games

每一個class位元組碼文件都唯一對應一個類或介面,class文件中記錄中類或介面的基本信息,但反之不成立,不是每一個類或介面都有一個唯一對應的位元組碼文件,首先類或介面的位元組碼可以不以文件的方式存儲,可以直接從記憶體中生成位元組碼,而不產生.class文件,動態代理的原理就是直接記憶體中生成位元組碼流,根據加 ...




hello world

 

class位元組碼文件

 

每一個class位元組碼文件都唯一對應一個類或介面,class文件中記錄中類或介面的基本信息,但反之不成立,不是每一個類或介面都有一個唯一對應的位元組碼文件,首先類或介面的位元組碼可以不以文件的方式存儲,可以直接從記憶體中生成位元組碼,而不產生.class文件,動態代理的原理就是直接記憶體中生成位元組碼流,根據載入位元組碼流進行類載入操作,類實例化,生成代理對象。

位元組碼文件記錄的信息:魔術,class文件主次版本,常量池數量及常量池表,類或介面的訪問標誌,類索引,超類索引,介面數量及介面表,欄位數量及欄位表,方法數量及方法表,屬性屬性及屬性表,jvm中使用類c結構體表示每一種屬性,結構體中類型種類有兩種,無符號數及表,以 _info結尾表示表,以 u1,u2,u4,u8分別表示1位元組,2位元組,4位元組,8位元組無符號數

ClassFile{
u4 magic;
u2 minor_version;
u2 major_version;
u2 constant_pool_count;
cp_info constant_pool[constant_pool_count];
u2 acc_flags;
u2 this_class;
u2 super_class;
u2 interfaces_count;
u2 interfaces[interfaces_count];
u2 fields_count;
field_info fields[fields_count];
u2 methods_count;
method_info methods[methods_count];
u2 attributes_count;
attribute_info attributes[attributes_count];
}

魔術:四個位元組,用於定義此位元組碼文件是否符合虛擬機規範,保證位元組碼文件不會威脅虛擬機的安全,若為cafebabe則表示位元組碼符合虛擬機規範

主次版本號:四個位元組,前兩位元組表示次版本號,後兩位元組表示主版本號,用於定義編譯的位元組碼文件格式版本,低版本虛擬機拒絕運行高版本位元組碼文件,但高版本虛擬機會向下相容低版本位元組碼文件

常量池數量及常量池表:這部分主要統計類或介面的字面量和符號引用,用於每個類或介面擁有的字面量和符號引用屬性不一定相同,所有需要兩個位元組的長度來表示常量池數目,常量池數目計數從1開始,比如類或介面中總共有兩個字面量符號引用,則常量池數目為2,註意,不是從0開始計數,0可能另有用處,可以用來表示類或介面中未出現的引用,用來表示超級父類java.long.Object全限定名的索引,常量池表是一個數組,一共有18種類型,每一種類型有一個tag屬性與之對應,constant_utf8_info用於表示文本字元串,類和介面全限定名,欄位名稱及描述符,方法名稱及描述符等常量信息,constant_integer_info用於存儲int類型的常量信息,只存儲int類型的值,不存儲其他符合引用信息,比如 final int a=1 符號引用信息為a,值為1,constant_float_info用於存儲float類型常量信息,也是只存儲float值,不存儲引用信息,constant_long_info用於存儲long類型的常量信息,constant_double_info用於存儲double類型的常量信息,constant_class_info用於存儲指向常量池列表constant_unf8_info類和介面全限定名的有效引用,constant_string_info用於存儲指定常量池列表constant_utf8_info某常量項的有效索引,指向文本字元串,constant_fieldref_info用於存儲指向常量池列表constant_class_info常量項和constant_nameandtype_info常量項的有效索引,constant_methodref_info用於存儲指向常量池列表constant_class_info常量項和constant_nameandtype_info常量項的有效索引,constant_interfacemethodref_info用於存儲指向常量池列表constant_class_info常量項和constant_nameandtype_info常量項的有效索引,constant_nameandtype_info用於存儲指向常量池列表constant_utf8_info常量項的有效索引,可以通過所有找到對應類及描述符,constant_methodtype_info用於存儲指向常量池constant_utf8_info常量項,表示方法類型,找到對應的方法描述符,constant_methodhandle_info用於表示方法句柄,屬性reference_kind表示方法句柄的類型,1-4表示為欄位創建的方法句柄,5-8表示為類方法(構造、實例、靜態)創建的句柄,9表示為介面方法創建的句柄,reference_index屬性指向根據reference_kind對應的常量池列表,constant_invokedynamic_info用於存儲當前位元組碼文件中引導方法bootstrap_method數組的有效索引和指向常量池constant_nameandtype_info常量項的有效索引

constant_utf8_info{
u1 tag;
u2 length;
u1 bytes[length];
}
constant_integer_info{
u1 tag;
u4 bytes;
}
constant_float_info{
u1 tag;
u4 float;
}
constant_long_info{
u1 falg;
u8 long;
}
constant_double_info{
u1 tag;
u4 double;
}
constant_class_info{
u1 tag;
u2 name_index;
}
constant_string_info{
u1 tag;
u2 string_index;
}
constant_fieldref_info{
u1 tag;
u2 class_index;
u2 name_and_type_index;
}
constant_mathodref_info{
u1 tag;
u2 class_index;
u2 name_and_type_index;
}
constant_interfacemathodref_info{
u1 tag;
u2 class_index;
u2 name_and_type_index;
}
constant_nameandtype_info{
u1 tag;
u2 class_index;
u2 descriptor_index;
}
constant_methodhandle_info{
u1 tag;
u2 reference_kind;
u2 reference_index;
}
constant_methodtype_info{
u1 tag;
u2 descriptor_index;
}
constant_invokedynamic_info{
u1 tag;
u2 bootstrap_method_attr_index;
u2 name_and_type_index;
}

訪問標誌:兩個位元組,用於定義位元組碼文件所表示的類或介面的訪問許可權,如判斷是類還是介面,類是否被abstract修飾,類是否被final修飾,  acc_interface表示是介面,acc_annotation表示是註解類型,acc_enum表示是枚舉類型,acc_public 表示類或介面是public訪問許可權,acc_final表示類不允許被繼承,acc_abstract表示類為抽象類,acc_super表示類調用實例方法時需進行特殊操作

類索引及父類索引:四個位元組,用於存儲指向常量池constant_class_info對應的有效索引,而constant_class_info存儲常量池列表的constant_utf8_info常量項索引,根據此索引可找到類和父類的全限定名

介面數量及介面表:介面屬性用於存儲當前類或介面的直接超類介面數量,介面表是一個數組,記住,只有常量池表從1開始計數,其餘都是從數組下表0開始計數,介面表數組的每一個數組元素存儲此類或介面的直接超類介面的有效索引,根據此索引找到constant_class_info對應的常量項,根據constant_class_info可找到對應直接超類介面的全限定名

欄位數量及欄位表:欄位數量用於存儲類或介面的欄位數目,包括類欄位和實例欄位,欄位表為一個數組,每一個數組元素都相當於一個field_info結構的對象,field_info結構包含欄位完整信息:欄位標識符,欄位訪問修飾符,欄位是類欄位還是實例欄位,欄位是否為常量等,註意:此處欄位表示當前類或介面的欄位,不包括從超類或介面繼承的欄位,java語法規範不允許同一個類或介面中出現同一欄位名的不同欄位,但是class文件中卻可以允許出現相同欄位名的不同欄位,只有欄位的描述符不同即可,field_info結構屬性:access_flags用於存儲欄位的訪問標誌,acc_private,acc_protected,acc_public,acc_final,acc_static,acc_volatile等,註意:acc_final與acc_volatile不能同時出現在同一欄位,name_index指向常量池constant_utf8_info常量項的有效索引,獲取當前欄位的簡單名稱,descriptor_index指向常量池constant_utf8_info常量項的有效索引,獲取當前欄位的描述符,attribute_count,attributes[attributes_count]這兩項表示欄位的屬性信息,用於描述欄位相關信息,attribute數組每一個元素都是一個attribute_info結構的元素

field_info{
u2 access_flags;
u2 name_index;
u2 descriptor_index;
u2 attributes_count;
attribute_info attributes[attribuyes_count];
}

方法數量及方法表:方法數量用於存儲當前類或介面的方法數目,包括實例方法,類方法,抽象方法,方法表是一個數組,每一個數組元素都是一個method_info結構,method_info結構包含方法的完整信息:方法描述符,訪問修飾符,是否為final方法,是否為abstract方法等,註意:此處的方法數組只是表示當前類或介面的所有方法,並不包括從超類及父介面繼承來的方法,java語法規範java類或介面中不允許出現方法簽名完全一樣的方法同時出現,會編譯報錯,而位元組碼層面卻允許方法簽名完全相同的方法同時出現,只需要保證方法的返回值類型不同,method_info結構屬性與field_info一致,但acc_flags類型不盡相同,註意acc_abstract不能與acc_final,acc_static,acc_private,acc_synchronized,acc_native同時使用,介面方法中只能使用acc_public,acc_abstract,此處我有一個疑問,介面中default方法有沒有對應的訪問標誌,註意:<init>方法只能使用acc_private,acc_protected,acc_public訪問標誌

method_info{
u2 access_flags;
u2 name_index;
u2 descriptor_index;
u2 attributes_count;
attribute_info attributes[attribuyes_count];
}

屬性數量及屬性表:屬性數量表示當前位元組碼文件中attribute_info表數目,屬性表是一個數組,每一個數組元素都是attribute_info結構,attribute_info結構表示屬性的完整信息:第一項指向常量池constant_utf8_info某常量項的有效索引,根據此索引可找到屬性對應名稱,屬性可以出現在classFile,欄位表,方法表中,用以描述相關信息,attribute_info結構完整信息:attribute_name_index指向常量池constant_utf8_info常量項的有效索引,獲取屬性名稱,attribute_length用於指明info數組長度,info[attribute_length]用於存儲屬性的數據信息,必須實現的數據信息:Code,ConstantValue,Exceptions,  code屬性用於描述method_info的具體相關信息,attribute_name_index指向常量池constant_utf8_info常量項的有效索引,獲取屬性名稱,即code,attribute_length表示attribute表示attribute_info長度,不包括attribute_name_index和attribute_length的初始6位元組,max_stack描述當前方法最大棧深度,max_locals描述當前方法的局部變數表,code_length表示code數組長度,code[]表示當前方法編譯後的位元組碼,  ContantVaue位於field_info結構中,用於通知虛擬機對類變數進行初始化,即欄位需要被acc_static修飾,當前類常量不需要ContantValue通知虛擬機執行初始化,早就執行好了,實例欄位此時不需要初始化

attribute_info{
u2 attribute_name_index;
u4 attribute_length;
u1 info[attribute_length];
}
code_attribute{
u2 attribute_name_index;
u4 attribute_length;
u2 max_stack;
u2 max_locals;
u4 code_length;
u1 code[code_length];
u2 exception_table_length;
exception_info exception_table[exception_table_length];
u2 attributes_count;
attribute_info attributes[attributes_count];
}
constantvalue_attribute{ u2 attribute_name_index;
u4 attribute_length;
u2 constantvalue_index;
}

 

簡單名稱與描述符:

簡單名稱是指欄位或方法的簡單的一種描述,比如person class:private String name欄位簡單名稱為name,Object class:public String toString()方法簡單名稱為toString,註意:欄位或方法簡單名稱不允許出現  .  :  / [ 等ASSIC或Unicode字元表示形式

描述符一般指欄位或方法的類型,欄位描述符表示欄位類型描述,方法描述符表示參數描述與返回值描述,如:person class:private String name欄位描述符為Ljava.lang.Object,com.test.Person class:setName(String name)方法描述符為(Ljava.lang.String)V,註意:其中V表示返回值為void類型,如果參數為void則表示為()Ljava.lang.Object,表示無參的返回值為java.lang.Object引用類型的方法描述符

欄位描述符解釋:B byte 位元組類型,Z boolean 布爾類型,C char 字元類型,S short 短整型,I 整型,L long 長整型,F float 單進度浮點類型,D double 雙精度浮點類型,L reference 對象引用類型,[ reference 數組引用類型

 

 

constant_mathodref_info{
u1 tag;
u2 class_index;
u2 name_and_type_index;
}


您的分享是我們最大的動力!

-Advertisement-
Play Games
更多相關文章
  • 函數 1.函數結構 def 是函數的定義關鍵字,my_len是函數名。()傳參用,冒號下麵都是函數體。 執行函數方法:函數名加括弧來執行函數。My_len() 舉例: # s = 'lkfjsjulkjdgjdsf' # def my_len(): # count = 0 # for i in s: ...
  • 我們或多或少都有過,或者見過將賦值表達式參與運算的情況。這通常會伴隨著一些意想不到的問題。今天我就見到了一段奇怪的代碼: 乍一看,似乎答案很明朗,按照順序運算之後,a的值是3,b的值是5.有經驗的程式員肯定會一眼看出,這裡的計算過程是一個未定義行為(Undefined behavior).在這裡簡單 ...
  • 這裡的內容僅僅是本人閱讀《Python高性能編程》後總結的一些知識,用於自己更好的瞭解Python機制。本人現在並不從事計算密集型工作:人工智慧、數據分析等。僅僅只是出於好奇而去閱讀這本書。很多人因為Python不能同時使用多顆CPU(全局解釋器鎖GIL),而覺得它不能實現高性能。書中有很多介紹避開 ...
  • 例1: 輸出結果: 例2: 輸出結果: ...
  • 1.建立普通的Javaweb項目,導入項目所必須的jar包。 2.配置web.xml文件。 3.在src下建立struts.xml。 4.在實體包下配置 實體名.hbm.xml 5.在src下建立applicationContext.xml。 6.在src下建立資料庫的相關配置信息db.proper ...
  • 實現步驟: 1、創建用戶登錄提交界面 2、創建處理用戶登錄請求servlet組件Main 3、創建代表登錄成功響應的servlet的組件LoginSuccess 4、創建代表登錄失敗響應的servlet組件LoginFail 【1代碼login.html】 【2程式Main.java】 【3程式Lo ...
  • Python作為一種解釋型語言,由於使用了全局解釋鎖(GIL)的原因,其代碼不能同時在多核CPU上併發的運行。這也導致在Python中使用多線程編程並不能實現併發,我們得使用其他的方法在Python中實現併發編程。 一、全局解釋鎖(GIL) Python中不能通過使用多線程實現併發編程主要是因為全局 ...
  • 使用繼承時,基類必須保證存在預設構造器(無參構造器),子類在實例化時,會首先自動調用隱式調用父類的無參構造器,允許子類與父類的構造器列表不一致,子類使用有參構造器實例化對象時,最好顯式調用父類構造器,防止出錯。 ...
一周排行
    -Advertisement-
    Play Games
  • 移動開發(一):使用.NET MAUI開發第一個安卓APP 對於工作多年的C#程式員來說,近來想嘗試開發一款安卓APP,考慮了很久最終選擇使用.NET MAUI這個微軟官方的框架來嘗試體驗開發安卓APP,畢竟是使用Visual Studio開發工具,使用起來也比較的順手,結合微軟官方的教程進行了安卓 ...
  • 前言 QuestPDF 是一個開源 .NET 庫,用於生成 PDF 文檔。使用了C# Fluent API方式可簡化開發、減少錯誤並提高工作效率。利用它可以輕鬆生成 PDF 報告、發票、導出文件等。 項目介紹 QuestPDF 是一個革命性的開源 .NET 庫,它徹底改變了我們生成 PDF 文檔的方 ...
  • 項目地址 項目後端地址: https://github.com/ZyPLJ/ZYTteeHole 項目前端頁面地址: ZyPLJ/TreeHoleVue (github.com) https://github.com/ZyPLJ/TreeHoleVue 目前項目測試訪問地址: http://tree ...
  • 話不多說,直接開乾 一.下載 1.官方鏈接下載: https://www.microsoft.com/zh-cn/sql-server/sql-server-downloads 2.在下載目錄中找到下麵這個小的安裝包 SQL2022-SSEI-Dev.exe,運行開始下載SQL server; 二. ...
  • 前言 隨著物聯網(IoT)技術的迅猛發展,MQTT(消息隊列遙測傳輸)協議憑藉其輕量級和高效性,已成為眾多物聯網應用的首選通信標準。 MQTTnet 作為一個高性能的 .NET 開源庫,為 .NET 平臺上的 MQTT 客戶端與伺服器開發提供了強大的支持。 本文將全面介紹 MQTTnet 的核心功能 ...
  • Serilog支持多種接收器用於日誌存儲,增強器用於添加屬性,LogContext管理動態屬性,支持多種輸出格式包括純文本、JSON及ExpressionTemplate。還提供了自定義格式化選項,適用於不同需求。 ...
  • 目錄簡介獲取 HTML 文檔解析 HTML 文檔測試參考文章 簡介 動態內容網站使用 JavaScript 腳本動態檢索和渲染數據,爬取信息時需要模擬瀏覽器行為,否則獲取到的源碼基本是空的。 本文使用的爬取步驟如下: 使用 Selenium 獲取渲染後的 HTML 文檔 使用 HtmlAgility ...
  • 1.前言 什麼是熱更新 游戲或者軟體更新時,無需重新下載客戶端進行安裝,而是在應用程式啟動的情況下,在內部進行資源或者代碼更新 Unity目前常用熱更新解決方案 HybridCLR,Xlua,ILRuntime等 Unity目前常用資源管理解決方案 AssetBundles,Addressable, ...
  • 本文章主要是在C# ASP.NET Core Web API框架實現向手機發送驗證碼簡訊功能。這裡我選擇是一個互億無線簡訊驗證碼平臺,其實像阿裡雲,騰訊雲上面也可以。 首先我們先去 互億無線 https://www.ihuyi.com/api/sms.html 去註冊一個賬號 註冊完成賬號後,它會送 ...
  • 通過以下方式可以高效,並保證數據同步的可靠性 1.API設計 使用RESTful設計,確保API端點明確,並使用適當的HTTP方法(如POST用於創建,PUT用於更新)。 設計清晰的請求和響應模型,以確保客戶端能夠理解預期格式。 2.數據驗證 在伺服器端進行嚴格的數據驗證,確保接收到的數據符合預期格 ...