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

本系列主要記錄筆者在學(xué)習(xí) [深入理解Java虛擬機(jī)] 一書時(shí)的理解
我們都知道在Java中赊级,我們并不需要過多的在意內(nèi)存的管理斩个,這一切都交給了虛擬機(jī)自動(dòng)管理爬虱,我們并不需要操心何時(shí)需要去釋放一個(gè)對(duì)象的內(nèi)存讳推。
當(dāng)然析砸,如果出現(xiàn)了內(nèi)存溢出或泄漏,我們就必須去了解一下Java虛擬機(jī)的內(nèi)存管理機(jī)制以便于我們解決問題
[筆者仍為Android初學(xué)者垮庐。如有解釋錯(cuò)誤的地方,歡迎評(píng)論區(qū)指正探討]

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


概述

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

  • 無符號(hào)數(shù)屬于基本的數(shù)據(jù)類型,以u(píng)1溉奕、u2褂傀、u4、u8來分別代表1個(gè)字節(jié)加勤、2個(gè)字節(jié)仙辟、4個(gè)字節(jié)和8個(gè)字節(jié)的無符號(hào)數(shù),無符號(hào)數(shù)可以用來描述數(shù)字鳄梅、索引引用叠国、數(shù)量值或者按照UTF-8編碼構(gòu)成字符串值。
  • 表是由多個(gè)無符號(hào)數(shù)或者其他表作為數(shù)據(jù)項(xiàng)構(gòu)成的復(fù)合數(shù)據(jù)類型戴尸,所有表都習(xí)慣性地以“_info”結(jié)尾粟焊。表用于描述有層次關(guān)系的復(fù)合結(jié)構(gòu)的數(shù)據(jù),整個(gè)Class文件本質(zhì)上就是一張表孙蒙。
類文件結(jié)構(gòu)

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

魔數(shù)Magic Number

每個(gè)Class文件的頭4個(gè)字節(jié)稱為魔數(shù)(Magic Number),它的唯一作用是確定這個(gè)文件是否為一個(gè)能被虛擬機(jī)接受的Class文件挎峦。很多文件存儲(chǔ)標(biāo)準(zhǔn)中都使用魔數(shù)來進(jìn)行*身份識(shí)別香追,譬如圖片格式,如gif或者jpeg等在文件頭中都存有魔數(shù)浑测。
使用魔數(shù)而不是擴(kuò)展名來進(jìn)行識(shí)別主要是基于安全方面的考慮翅阵,因?yàn)槲募U(kuò)展名可以隨意地改動(dòng)。

版本號(hào)

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

常量池

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

由于常量池?cái)?shù)量是不確定的,所以需要有一個(gè)u2類型的數(shù)據(jù)用來存儲(chǔ)常量池?cái)?shù)量贡定。

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

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

常量池中每一項(xiàng)常量都是一個(gè)表,看一下圖

常量池

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

訪問標(biāo)志

接下來的兩個(gè)直接表示訪問標(biāo)志,這個(gè)標(biāo)志用來識(shí)別一些類或接口層次的訪問信息腌巾,包括:這個(gè)class是類還是接口遂填,是不是public,是不是abstract澈蝙,是不是final等等信息吓坚。
access_flags中一共有16個(gè)標(biāo)志位可以使用,1為真灯荧,0為假礁击。

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

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

  • 類索引用于確定這個(gè)類的全限定名.
  • 父類索引用于確定這個(gè)類的父類的全限定名挚躯。由于Java語言不允許多重繼承,所以父類索引只有一個(gè)擦秽,除了java.lang.Object之外秧均,所有的Java類都有父類食侮,因此除了java.lang.Object外,所有Java類的父類索引都不為0目胡。
  • 接口索引集合就用來描述這個(gè)類實(shí)現(xiàn)了哪些接口,接口索引集合還有一個(gè)標(biāo)記(interface_count)链快,用來標(biāo)記實(shí)現(xiàn)了多少個(gè)接口誉己。

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

字段表集合

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

一個(gè)字段表中包含了字段的作用域(public筑累、private、protected修飾
符)丝蹭、是實(shí)例變量還是類變量(static修飾符)慢宗、可變性(final)、并發(fā)可見性(volatile修飾符奔穿,是否強(qiáng)制從主內(nèi)存讀寫)镜沽、可否被序列化(transient修飾符)、字段數(shù)據(jù)類型(基本類型贱田、對(duì)象缅茉、數(shù)組)、字段名稱等等信息男摧。
大部分信息都是用bool值來表示的蔬墩,是或者否。
而字段叫什么名字耗拓、字段被定義為什么數(shù)據(jù)類型拇颅,這些都是無法固定的,只能引用常量池中的常量來描述帆离。

方法表集合

類似于字段表蔬蕊,方法表依次包括了訪問標(biāo)志(access_flags)、名稱索引(name_index)哥谷、描述符索引(descriptor_index)岸夯、屬性表集合(attributes)等幾項(xiàng)。

常規(guī)的標(biāo)志都和字段表的標(biāo)志一樣们妥,用bool值來表示猜扮。
不過不同于字段的是,方法還應(yīng)該有方法代碼监婶,而這部分存放在屬性表的code字段里旅赢。屬性表是Class文件格式中最具擴(kuò)展性的一種數(shù)據(jù)項(xiàng)目齿桃,下面我們來了解一下屬性表。

屬性表

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

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

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

小結(jié)

類文件結(jié)構(gòu)大概就介紹到這里妈嘹,每一種表都有各自的屬性,但是無外乎都記錄了我們?cè)瓉韏ava文件中寫的一些屬性绍妨,變量润脸,方法的信息。這些信息多種多樣他去,這里就不深入闡述毙驯,簡(jiǎn)單了解。

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
  • 序言:七十年代末灾测,一起剝皮案震驚了整個(gè)濱河市爆价,隨后出現(xiàn)的幾起案子,更是在濱河造成了極大的恐慌媳搪,老刑警劉巖铭段,帶你破解...
    沈念sama閱讀 206,126評(píng)論 6 481
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件,死亡現(xiàn)場(chǎng)離奇詭異秦爆,居然都是意外死亡序愚,警方通過查閱死者的電腦和手機(jī),發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 88,254評(píng)論 2 382
  • 文/潘曉璐 我一進(jìn)店門等限,熙熙樓的掌柜王于貴愁眉苦臉地迎上來爸吮,“玉大人芬膝,你說我怎么就攤上這事⌒谓浚” “怎么了锰霜?”我有些...
    開封第一講書人閱讀 152,445評(píng)論 0 341
  • 文/不壞的土叔 我叫張陵,是天一觀的道長(zhǎng)桐早。 經(jīng)常有香客問我锈遥,道長(zhǎng),這世上最難降的妖魔是什么勘畔? 我笑而不...
    開封第一講書人閱讀 55,185評(píng)論 1 278
  • 正文 為了忘掉前任,我火速辦了婚禮丽惶,結(jié)果婚禮上炫七,老公的妹妹穿的比我還像新娘。我一直安慰自己钾唬,他們只是感情好万哪,可當(dāng)我...
    茶點(diǎn)故事閱讀 64,178評(píng)論 5 371
  • 文/花漫 我一把揭開白布。 她就那樣靜靜地躺著抡秆,像睡著了一般奕巍。 火紅的嫁衣襯著肌膚如雪。 梳的紋絲不亂的頭發(fā)上儒士,一...
    開封第一講書人閱讀 48,970評(píng)論 1 284
  • 那天的止,我揣著相機(jī)與錄音,去河邊找鬼着撩。 笑死诅福,一個(gè)胖子當(dāng)著我的面吹牛,可吹牛的內(nèi)容都是我干的拖叙。 我是一名探鬼主播氓润,決...
    沈念sama閱讀 38,276評(píng)論 3 399
  • 文/蒼蘭香墨 我猛地睜開眼,長(zhǎng)吁一口氣:“原來是場(chǎng)噩夢(mèng)啊……” “哼薯鳍!你這毒婦竟也來了咖气?” 一聲冷哼從身側(cè)響起,我...
    開封第一講書人閱讀 36,927評(píng)論 0 259
  • 序言:老撾萬榮一對(duì)情侶失蹤挖滤,失蹤者是張志新(化名)和其女友劉穎崩溪,沒想到半個(gè)月后,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體壶辜,經(jīng)...
    沈念sama閱讀 43,400評(píng)論 1 300
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡悯舟,尸身上長(zhǎng)有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 35,883評(píng)論 2 323
  • 正文 我和宋清朗相戀三年,在試婚紗的時(shí)候發(fā)現(xiàn)自己被綠了砸民。 大學(xué)時(shí)的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片抵怎。...
    茶點(diǎn)故事閱讀 37,997評(píng)論 1 333
  • 序言:一個(gè)原本活蹦亂跳的男人離奇死亡奋救,死狀恐怖,靈堂內(nèi)的尸體忽然破棺而出反惕,到底是詐尸還是另有隱情尝艘,我是刑警寧澤,帶...
    沈念sama閱讀 33,646評(píng)論 4 322
  • 正文 年R本政府宣布姿染,位于F島的核電站背亥,受9級(jí)特大地震影響,放射性物質(zhì)發(fā)生泄漏悬赏。R本人自食惡果不足惜狡汉,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 39,213評(píng)論 3 307
  • 文/蒙蒙 一、第九天 我趴在偏房一處隱蔽的房頂上張望闽颇。 院中可真熱鬧盾戴,春花似錦、人聲如沸兵多。這莊子的主人今日做“春日...
    開封第一講書人閱讀 30,204評(píng)論 0 19
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽剩膘。三九已至衅斩,卻和暖如春,著一層夾襖步出監(jiān)牢的瞬間怠褐,已是汗流浹背畏梆。 一陣腳步聲響...
    開封第一講書人閱讀 31,423評(píng)論 1 260
  • 我被黑心中介騙來泰國(guó)打工, 沒想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留惫搏,地道東北人具温。 一個(gè)月前我還...
    沈念sama閱讀 45,423評(píng)論 2 352
  • 正文 我出身青樓,卻偏偏與公主長(zhǎng)得像筐赔,于是被迫代替她去往敵國(guó)和親铣猩。 傳聞我的和親對(duì)象是個(gè)殘疾皇子,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 42,722評(píng)論 2 345

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

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