JVM解析——類文件結(jié)構(gòu)

本系列主要記錄筆者在學習 [深入理解Java虛擬機] 一書時的理解
我們都知道在Java中,我們并不需要過多的在意內(nèi)存的管理,這一切都交給了虛擬機自動管理,我們并不需要操心何時需要去釋放一個對象的內(nèi)存。
當然,如果出現(xiàn)了內(nèi)存溢出或泄漏,我們就必須去了解一下Java虛擬機的內(nèi)存管理機制以便于我們解決問題
[筆者仍為Android初學者。如有解釋錯誤的地方,歡迎評論區(qū)指正探討]

本篇為該系列第四篇,概述類文件結(jié)構(gòu)。


概述

想要深入的了解Jvm,那么解析class文件是必不可少的,Class文件格式采用一種類似于C語言結(jié)構(gòu)體的偽結(jié)構(gòu)來存儲數(shù)據(jù),這種偽結(jié)構(gòu)中只有兩種數(shù)據(jù)類型:無符號數(shù)和表。

  • 無符號數(shù)屬于基本的數(shù)據(jù)類型,以u1、u2、u4、u8來分別代表1個字節(jié)、2個字節(jié)、4個字節(jié)和8個字節(jié)的無符號數(shù),無符號數(shù)可以用來描述數(shù)字、索引引用、數(shù)量值或者按照UTF-8編碼構(gòu)成字符串值。
  • 表是由多個無符號數(shù)或者其他表作為數(shù)據(jù)項構(gòu)成的復合數(shù)據(jù)類型,所有表都習慣性地以“_info”結(jié)尾。表用于描述有層次關(guān)系的復合結(jié)構(gòu)的數(shù)據(jù),整個Class文件本質(zhì)上就是一張表
類文件結(jié)構(gòu)

接下來我們依照這張圖,一步一步的解析類文件的結(jié)構(gòu):

魔數(shù)Magic Number

每個Class文件的頭4個字節(jié)稱為魔數(shù)(Magic Number),它的唯一作用是確定這個文件是否為一個能被虛擬機接受的Class文件。很多文件存儲標準中都使用魔數(shù)來進行*身份識別,譬如圖片格式,如gif或者jpeg等在文件頭中都存有魔數(shù)。
使用魔數(shù)而不是擴展名來進行識別主要是基于安全方面的考慮,因為文件擴展名可以隨意地改動。

版本號

緊接著魔數(shù)的是版本號,分為次版本號和主版本號,高版本的JDK能向下兼容以前版本的Class文件,但不能運行以后版本的Class文件,即使文件格式并未發(fā)生任何變化,虛擬機也必須拒絕執(zhí)行超過其版本號的Class文件。

常量池

接下來是常量池,常量池可以理解為Class文件之中的資源倉庫,
它是Class文件結(jié)構(gòu)中與其他項目關(guān)聯(lián)最多的數(shù)據(jù)類型,也是占用Class文件空間最大的數(shù)據(jù)項目之一,同時它還是在Class文件中第一個出現(xiàn)的表類型數(shù)據(jù)項目。

由于常量池數(shù)量是不確定的,所以需要有一個u2類型的數(shù)據(jù)用來存儲常量池數(shù)量。

常量池主要存放兩大類常量:字面量符號引用。字面量指的是文本字符串、聲明為final的常量值等。而而符號引用則屬于編譯原理方面的概念,包括:類和接口的全限定名,字段的名稱和描述符,方法的名稱和描述符。

Java代碼在進行Javac編譯的時候,并不像C和C++那樣有“連接”這一步驟,而是在虛擬機加載Class文件的時候進行動態(tài)連接。也就是說,在Class文件中不會保存各個方法、字段的最終內(nèi)存布局信息,因此這些字段、方法的符號引用不經(jīng)過運行期轉(zhuǎn)換的話無法得到真正的內(nèi)存入口地址,也就無法直接被虛擬機使用。當虛擬機運行時,需要從常量池獲得對應的符號引用,再在類創(chuàng)建時或運行時解析、翻譯到具體的內(nèi)存地址之中。

常量池中每一項常量都是一個表,看一下圖

常量池

表里存儲的各種類型的數(shù)據(jù)的一些信息,這里就不深入展開了。

訪問標志

接下來的兩個直接表示訪問標志,這個標志用來識別一些類或接口層次的訪問信息,包括:這個class是類還是接口,是不是public,是不是abstract,是不是final等等信息。
access_flags中一共有16個標志位可以使用,1為真,0為假。

類索引,父類索引,接口索引集合

類索引(this_class)和父類索引(super_class)都是一個u2類型的數(shù)據(jù),而接口索引集合(interfaces)是一組u2類型的數(shù)據(jù)的集合。
Class文件中由這三項數(shù)據(jù)來確定這個類的繼承關(guān)系。

  • 類索引用于確定這個類的全限定名.
  • 父類索引用于確定這個類的父類的全限定名。由于Java語言不允許多重繼承,所以父類索引只有一個,除了java.lang.Object之外,所有的Java類都有父類,因此除了java.lang.Object外,所有Java類的父類索引都不為0。
  • 接口索引集合就用來描述這個類實現(xiàn)了哪些接口,接口索引集合還有一個標記(interface_count),用來標記實現(xiàn)了多少個接口。

這些索引值各自指向一個類型為CONSTANT_Class_info的類描述符常量,通過CONSTANT_Class_info類型的常量中的索引值可以找到定義在CONSTANT_Utf8_info類型的常量中的全限定名字符串。

字段表集合

字段表(field_info)用于描述接口或者類中聲明的變量。字段(field)包括類級變量以及實例級變量,但不包括在方法內(nèi)部聲明的局部變量。

一個字段表中包含了字段的作用域(public、private、protected修飾
符)、是實例變量還是類變量(static修飾符)、可變性(final)、并發(fā)可見性(volatile修飾符,是否強制從主內(nèi)存讀寫)、可否被序列化(transient修飾符)、字段數(shù)據(jù)類型(基本類型、對象、數(shù)組)、字段名稱等等信息。
大部分信息都是用bool值來表示的,是或者否。
而字段叫什么名字、字段被定義為什么數(shù)據(jù)類型,這些都是無法固定的,只能引用常量池中的常量來描述。

方法表集合

類似于字段表,方法表依次包括了訪問標志(access_flags)、名稱索引(name_index)、描述符索引(descriptor_index)、屬性表集合(attributes)等幾項。

常規(guī)的標志都和字段表的標志一樣,用bool值來表示。
不過不同于字段的是,方法還應該有方法代碼,而這部分存放在屬性表的code字段里。屬性表是Class文件格式中最具擴展性的一種數(shù)據(jù)項目,下面我們來了解一下屬性表。

屬性表

屬性表(attribute_info)在前面的講解之中已經(jīng)出現(xiàn)過數(shù)次,在Class文件、字段表、方法表都可以攜帶自己的屬性表集合,以用于描述某些場景專有的信息。

與Class文件中其他的數(shù)據(jù)項目要求嚴格的順序、長度和內(nèi)容不同,屬性表集合的限制稍微寬松了一些,不再要求各個屬性表具有嚴格順序,并且只要不與已有屬性名重復,任何人實現(xiàn)的編譯器都可以向?qū)傩员碇袑懭胱约憾x的屬性信息

屬性表中可以包括很多信息,比如方法代碼(code),常量值(ConstantValue),異常(Exceptions),源文件名稱(SourceFile)等等信息,對于每個屬性,它的名稱需要從常量池中引用一個CONSTANT_Utf8_info類型的常量來表示,而屬性值的結(jié)構(gòu)則是完全自定義的,只需要通過一個u4的長度屬性去說明屬性值所占用的位數(shù)即可。

小結(jié)

類文件結(jié)構(gòu)大概就介紹到這里,每一種表都有各自的屬性,但是無外乎都記錄了我們原來java文件中寫的一些屬性,變量,方法的信息。這些信息多種多樣,這里就不深入闡述,簡單了解。

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
平臺聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點,簡書系信息發(fā)布平臺,僅提供信息存儲服務。
  • 序言:七十年代末,一起剝皮案震驚了整個濱河市,隨后出現(xiàn)的幾起案子,更是在濱河造成了極大的恐慌,老刑警劉巖,帶你破解...
    沈念sama閱讀 228,505評論 6 533
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件,死亡現(xiàn)場離奇詭異,居然都是意外死亡,警方通過查閱死者的電腦和手機,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 98,556評論 3 418
  • 文/潘曉璐 我一進店門,熙熙樓的掌柜王于貴愁眉苦臉地迎上來,“玉大人,你說我怎么就攤上這事。” “怎么了?”我有些...
    開封第一講書人閱讀 176,463評論 0 376
  • 文/不壞的土叔 我叫張陵,是天一觀的道長。 經(jīng)常有香客問我,道長,這世上最難降的妖魔是什么? 我笑而不...
    開封第一講書人閱讀 63,009評論 1 312
  • 正文 為了忘掉前任,我火速辦了婚禮,結(jié)果婚禮上,老公的妹妹穿的比我還像新娘。我一直安慰自己,他們只是感情好,可當我...
    茶點故事閱讀 71,778評論 6 410
  • 文/花漫 我一把揭開白布。 她就那樣靜靜地躺著,像睡著了一般。 火紅的嫁衣襯著肌膚如雪。 梳的紋絲不亂的頭發(fā)上,一...
    開封第一講書人閱讀 55,218評論 1 324
  • 那天,我揣著相機與錄音,去河邊找鬼。 笑死,一個胖子當著我的面吹牛,可吹牛的內(nèi)容都是我干的。 我是一名探鬼主播,決...
    沈念sama閱讀 43,281評論 3 441
  • 文/蒼蘭香墨 我猛地睜開眼,長吁一口氣:“原來是場噩夢啊……” “哼!你這毒婦竟也來了?” 一聲冷哼從身側(cè)響起,我...
    開封第一講書人閱讀 42,436評論 0 288
  • 序言:老撾萬榮一對情侶失蹤,失蹤者是張志新(化名)和其女友劉穎,沒想到半個月后,有當?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體,經(jīng)...
    沈念sama閱讀 48,969評論 1 335
  • 正文 獨居荒郊野嶺守林人離奇死亡,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點故事閱讀 40,795評論 3 354
  • 正文 我和宋清朗相戀三年,在試婚紗的時候發(fā)現(xiàn)自己被綠了。 大學時的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片。...
    茶點故事閱讀 42,993評論 1 369
  • 序言:一個原本活蹦亂跳的男人離奇死亡,死狀恐怖,靈堂內(nèi)的尸體忽然破棺而出,到底是詐尸還是另有隱情,我是刑警寧澤,帶...
    沈念sama閱讀 38,537評論 5 359
  • 正文 年R本政府宣布,位于F島的核電站,受9級特大地震影響,放射性物質(zhì)發(fā)生泄漏。R本人自食惡果不足惜,卻給世界環(huán)境...
    茶點故事閱讀 44,229評論 3 347
  • 文/蒙蒙 一、第九天 我趴在偏房一處隱蔽的房頂上張望。 院中可真熱鬧,春花似錦、人聲如沸。這莊子的主人今日做“春日...
    開封第一講書人閱讀 34,659評論 0 26
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽。三九已至,卻和暖如春,著一層夾襖步出監(jiān)牢的瞬間,已是汗流浹背。 一陣腳步聲響...
    開封第一講書人閱讀 35,917評論 1 286
  • 我被黑心中介騙來泰國打工, 沒想到剛下飛機就差點兒被人妖公主榨干…… 1. 我叫王不留,地道東北人。 一個月前我還...
    沈念sama閱讀 51,687評論 3 392
  • 正文 我出身青樓,卻偏偏與公主長得像,于是被迫代替她去往敵國和親。 傳聞我的和親對象是個殘疾皇子,可洞房花燭夜當晚...
    茶點故事閱讀 47,990評論 2 374

推薦閱讀更多精彩內(nèi)容

  • 國家電網(wǎng)公司企業(yè)標準(Q/GDW)- 面向?qū)ο蟮挠秒娦畔?shù)據(jù)交換協(xié)議 - 報批稿:20170802 前言: 排版 ...
    庭說閱讀 11,052評論 6 13
  • Spring Cloud為開發(fā)人員提供了快速構(gòu)建分布式系統(tǒng)中一些常見模式的工具(例如配置管理,服務發(fā)現(xiàn),斷路器,智...
    卡卡羅2017閱讀 134,785評論 18 139
  • Class文件是一組以8位字節(jié)為基礎(chǔ)單位的二進制流,各個數(shù)據(jù)項目按照順序緊湊地排列在Class文件中,中間沒有任何...
    maxwellyue閱讀 748評論 0 0
  • 夢到我們和好了,你在玩著游戲,我在旁邊陪著你,我問你有沒有看到我后來發(fā)的消息,你說你看到了。我說我后來也都刪掉了,...
    豬悟能閱讀 293評論 0 0
  • Time line of April Good evening, dear friends! It is real...
    小橙子April閱讀 168評論 0 0