JVM——类文件结构
1、概述
老師講過:“計算機只認識0和1,所以我們寫的程序需要經編譯器譯成由0和1構成的二進制格才能由計算機執行”。到由于最近10年內虛擬機以及大量建立再虛擬機之上的程序語言如雨后春筍般出現并蓬勃發展,將我們編寫的程序編譯成二進制本地機器碼已不再是唯一的選擇,越來越多的程序語言選擇了與操作系統和機器指令集無關的、平臺中立的格式作為程序編譯后的存儲格式。
java再誕生之時曾經提出一個非常著名的宣傳口號:“一次編譯,到處運行”,這句話充分表達了軟件開發人員對沖破平臺界限的渴求。
“與平臺無關性”的理想最終實現在操作系統的應用層上,sun公司以及其他虛擬機提供商發布了許多可以運行在各種不同的虛擬機,這些虛擬機都可以載入和執行同一種平臺無關的字節碼,從而實現了程序的“一次編譯,到處運行”。
各種不同平臺的虛擬機與所有的平臺都統一使用的程序存儲格式--字節碼(ByteCode)是構成平臺無關性的基石。
語言無關性正在越來越被開發者所重視。
到目前為止,或許大部分程序員都還認為Java虛擬機執行Java程序是一件理所當然和天經地義的事情。但是在java發展之初,設計者就曾經考慮過并實現了讓其它語言運行在Java虛擬機之上的可能性。并且在1997年發布的第一版Java虛擬機規范中就i曾經承諾鍋(在未來,我們會對Java虛擬機進行適當的擴展,以便更好的支持其他語言運行于JVM之上),JDK1.7開始就是兌現了這個承諾
時至今日,商業機構和開源機構已經在Java語言之外發展出一大堆在Java虛擬機之上運行的語言,如Clojure、Groovy、JRuby、Jython、Scala等。
實現語言無關性的基礎仍然是虛擬機和字節碼存儲格式。
Java虛擬機不和包括Java在內的任何語言綁定,它只與“Class文件”這種特定的二進制文件格式所關聯,Class文件中包含了Java虛擬機指令集和符號表已經若干其他輔助信息。
2、Class類文件的結構
注意:任何一個Class文件都對應著唯一一個類或接口的定義信息,但是反過來說,類或接口并不一定都的定義在文件里(譬如類或接口也可以通過類加載器直接生成)
Class文件是一組以8位字節為基礎單位的二進制流,各個數據項目嚴格按照順序緊湊地排列在Class文件之中,中間沒有添加任何分隔符,這使得整個Class文件中存儲的內容幾乎全部是程序運行必要的數據,沒有空隙存在
根據Java虛擬機規范規定,Class文件格式采用一種類似于C語言結構體的偽結構來存儲數據,這種偽結構中只有兩種數據類型:無符號數和表
無論是無符號數還是表,當需要描述同一類型但數量不定的多個數據時,經常會使用一個前置的容器計數器加若干個連續的數據項形式,這時稱這一系列連續的某一個類型的數據為某一類型的集合
2.1.1、魔數與Class文件的版本
每個Class文件的頭4個字節稱為魔數,他的唯一作用就是確定這個文件是否為一個能被虛擬機接受的Class文件。
緊接著魔數得的4個字節存儲的是Class文件的版本號:第5和第6字節是次版本號,第7和第8個字節是主版本號
上圖顯示的是使用十六進制編輯器打開的上面代碼生成的class文件,可以清楚的看見開頭4個字節表示的是0xCAFEBABE,代碼次版本號的第5個和第6個字節值為0x0000,而主版本號的值為0x0032,也即是十進制的50,該版本是可以被JDK1.6或以上版本虛擬機執行的Class文件。
2.1.2、常量池
緊接著主次版本號之后的是常量池入口,常量池可以理解為Class文件之中的資源倉庫,它是Class文件結構中與其他項目關聯最多的數據類型,也是占用Class文件空間最大的數據項目之一,同時他還是再Class文件中第一個出現的表類型數據項目。
由于常量池中常量的數量是不固定的,所以再常量池的入口需要放置一項u2類型的數據,代表常量池容量計數值。與Java中語言習慣不一樣的是,這個容量計數是從1而不是從0開始。
Class文件結構中只有常量池的容量計數是從1開始,對于其他集合類型,包括接口索引集合,字段表集合,方法表集合等的容量計數都與一般習慣相同,是從0開始的。
上圖,常量池容量為十六進制0x0016,即十進制的22,這是代表常量池中有21項常量,索引值為1~21
常量池中主要存在兩大類常量:字面量和符號引用字面量比較接近與java語言層面的常量概念,如文本字符串、聲明為final的常量值等。而符號引用則屬于編譯原理方面的概念包,包括了下面三類常量:
| 字段的名稱和描述符 |
| 方法的名稱和描述符 |
Java代碼在進行Javac編譯的時候,是在虛擬機加載Class文件的時候進行動態連接,也就是說,在Class文件中不會保存各個方法、字段的最終內存布局信息,因此這些字段、方法的符號引用不經過運行期轉行的話無法等到真正的內存入口地址,也就無法直接被虛擬機使用。當虛擬機運行時,需要從常量池獲得對應的符號引用,再在類創建時或運行時解析到具體的內存地址之中。
常量池中每一項常量都是一個表,在JDK1.7之前共有11種結構不相同的表結構數據。在JDK1.7中為了更好的支持動態語言調用,又額外增加了3種。如下圖
轉載于:https://juejin.im/post/5cdaec455188250a6e5c6c2c
創作挑戰賽新人創作獎勵來咯,堅持創作打卡瓜分現金大獎總結
以上是生活随笔為你收集整理的JVM——类文件结构的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: 梦到别人流产了是什么意思
- 下一篇: 梦到自己头发变白是怎么回事