[jvm虛擬機(jī)]class類文件結(jié)構(gòu)

Technical--Documentation

共享技術(shù)文檔

項(xiàng)目簡介

為為日常工作和學(xué)習(xí)的總結(jié)。

技術(shù)文檔主站簡介

主站文檔是我在前人的腳步上對研發(fā)的學(xué)習(xí)和總結(jié)紀(jì)錄厘肮,在以后的日子里良漱,我會將自己研發(fā)工作中所可能遇見問題和心得在這里紀(jì)錄下來舞虱,公開的分享。世界的存在很美好母市,開源的存在很精彩矾兜。從今天起,我便借助開源的力量患久,向改變?nèi)祟惖纳罘绞竭@條路邁進(jìn)椅寺。

點(diǎn)擊這里直接進(jìn)入為為技術(shù)文檔主站,或者訪問 https://weiwei02.github.io/Technical--Documentation/
與文檔配套的 Technical--Documentation項(xiàng)目的地址是 https://github.com/weiwei02/Technical--Documentation

*.class文件介紹

一般來講.class文件是.java文件在編譯器編譯后生成的jvm能夠運(yùn)行的文件蒋失,*.class文件又常被稱為字節(jié)碼文件返帕。java在創(chuàng)始之初,就提倡“一次編寫篙挽,處處運(yùn)行的概念”荆萤,在當(dāng)今編程圈中這個概念早已不是什么特例。java通過將開發(fā)人員所編寫的java代碼編譯成class文件铣卡,然后由jvm虛擬機(jī)在執(zhí)行時將不分平臺的class文件中的字節(jié)碼链韭,再翻譯成機(jī)器碼,交給硬件執(zhí)行煮落。java就是靠jvm虛擬機(jī)的這個設(shè)計(jì)來實(shí)現(xiàn)與平臺無關(guān)的特性的敞峭。class文件不但與硬件平臺和操作系統(tǒng)無關(guān),也和具體的編程語言無關(guān)蝉仇,就目前來說旋讹,如函數(shù)式編程語言scala與Groovy都可以通過自己的編譯器將源代碼編譯成class文件殖蚕,在jvm上運(yùn)行。
綜合來講骗村,class文件有以下兩點(diǎn)特性:

  • 與硬件和操作系統(tǒng)平臺無關(guān)
  • 與源碼所使用的編程語言無關(guān)

class類文件的結(jié)構(gòu)

每一個class文件都唯一對應(yīng)著java類或接口枚舉等定義信息嫌褪,但類不一定都定義在class文件中,類可能是由類加載器動態(tài)生成的胚股。

class文件所以被稱之為字節(jié)碼據(jù)我猜測可能是因?yàn)閏lass文件以8位(1字節(jié))為單位進(jìn)行存儲的二進(jìn)制信息笼痛。字節(jié)碼中各個數(shù)據(jù)項(xiàng)目嚴(yán)格按照順序緊湊的排列,中間沒有任何分割符琅拌。在需要存儲整型或浮點(diǎn)型這些大于8位的數(shù)據(jù)項(xiàng)目時缨伊,則會使用Big-Endian的字節(jié)序進(jìn)行存儲进宝,將最高位字節(jié)放在地址最低位刻坊,最低位字節(jié)放在地址最高位。

class文件格式采用表來存儲數(shù)據(jù)党晋,表中有無符號數(shù)和表兩種數(shù)據(jù)類型谭胚。對于這兩種數(shù)據(jù)類型說明如下:

  • 無符號數(shù): 無符號數(shù)是基本的數(shù)據(jù)類型,可以用來表示數(shù)字未玻、索引引用灾而、數(shù)量值或者按照UTF-8編碼構(gòu)成的字符串。如u1,u2,u4,u8分別代表1,2,4,8個字節(jié)字節(jié)的無符號數(shù)扳剿。
  • : 表是由多個無符號數(shù)或者其它表作為數(shù)據(jù)項(xiàng)所組成的復(fù)合數(shù)據(jù)結(jié)構(gòu)旁趟,表用于描述層次關(guān)系和復(fù)合的數(shù)據(jù)結(jié)構(gòu),整個class文件就是一張表庇绽。通常表以 _info 結(jié)尾锡搜。如表1就是一個class的表示例。
類型 名稱 數(shù)量
u4 magic 1
u2 minor_version 1
u2 major_version 1
u2 constant_pool_count 1
cp_info constant_pool constant_pool_count - 1
u2 asscess_flags 1
u2 this_class 1
u2 super_class 1
u2 interfaces_count 1
u2 interfaces interfaces_count
u2 fields_count 1
field_info fields fields_count
u2 methods_count 1
method_info methods method_count
u2 attributes_count 1
attribute_info attributes attributes_count

表 1 class文件格式

class文件的順序和格式必須嚴(yán)格實(shí)現(xiàn)按照上述規(guī)則瞧掺,否則jvm將不能識別執(zhí)行耕餐。

Magic Number 魔數(shù)

魔數(shù)是一個和文件后綴名相似的用于文件格式識別的約定,一般規(guī)定文件內(nèi)容開頭的前幾個字節(jié)為文件的魔數(shù)辟狈。不同于文件后綴名很容易被用戶以重命名的方式進(jìn)行更改肠缔,文件的魔數(shù)作為識別手段可以更安全的確定文件的可用性。

class文件使用前4個字節(jié)作為魔數(shù)上陕,來確定.class文件是否是一個能夠被虛擬機(jī)識別的文件桩砰,其值是 0xCAFFEBABE 拓春。

版本

class文件的第5-6個字節(jié)代表的可執(zhí)行該class文件的目標(biāo)虛擬機(jī)的最低次版本號(Minor Version)释簿,第7-8個字節(jié)是主版本號(Major Version)。java虛擬機(jī)可以運(yùn)行比當(dāng)前虛擬機(jī)版本號低的class文件硼莽,拒絕運(yùn)行版本號不合法庶溶,或比自己版本高的class文件煮纵。JDK1.1的版本號是45,之后的每個大版本發(fā)布都把主版本號加1,如JDK1.2主版本號是46,JDK8的版本號是52撑碴。
JDK在編譯java文件是可以通過 javac -target 1.6 ...命令來指定編譯后的class文件可以在1.6的虛擬機(jī)版本上運(yùn)行宵睦。

常量池

常量池是class文件中第一個表類型的數(shù)據(jù)項(xiàng)目,常量池是class文件中的資源倉庫瞬痘,是class文件結(jié)構(gòu)中與其它項(xiàng)目關(guān)聯(lián)最多的數(shù)據(jù)類型,也是占用class文件空間最大的數(shù)據(jù)項(xiàng)目之一。

class文件里緊隨版本之后的數(shù)據(jù)項(xiàng)是常量池贞让,由于常量池的數(shù)量是不固定的,所以在常量池的數(shù)據(jù)項(xiàng)之前放置的有一個u2類型的數(shù)據(jù)柳譬,代表常量池的大小喳张。常量池大小的初始值是1,如常量池的大小的數(shù)據(jù)如果顯示的是10美澳,就代表該class文件中有9個常量销部。
常量池中主要存放兩大類常量:Literal(字面常量)、Symbolic Reference(符號引用常量)制跟。字面常量類似于java中常量的概念舅桩,如文本字符串、final關(guān)鍵字所聲明的常量等凫岖。而符號引用常量則是編譯中的概念江咳,主要包括以下三種類型的常量。

  • 符號常量
+ 類和接口的全限定名(Fully Qualified Name)
+ 字段名稱和描述符(Descriptor)
+ 方法的名稱和描述符

class文件中不會保存各個方法或字段在內(nèi)存中的布局信息哥放,而是在虛擬機(jī)加載class文件時進(jìn)行動態(tài)的連接歼指。虛擬機(jī)在運(yùn)行class文件時從常量池中獲取對應(yīng)的符號引用,再在創(chuàng)建類或者運(yùn)行時解析連接到具體的內(nèi)存地址當(dāng)中甥雕。
常量池中的每一個常量都是一個表踩身,在JDK8中有14種表結(jié)構(gòu)的常量表。如表 2 所示社露。

類型 標(biāo)識 描述
CONSTANT_utf8_info 1 UTF-8編碼的字符串
CONSTANT_Integer_info 3 整形字面量
CONSTANT_Float_info 4 浮點(diǎn)型字面量
CONSTANT_Long_info 長整型字面量
CONSTANT_Double_info 雙精度浮點(diǎn)型字面量
CONSTANT_Class_info 類或接口的符號引用
CONSTANT_String_info 字符串類型字面量
CONSTANT_Fieldref_info 字段的符號引用
CONSTANT_Methodref_info 10 類中方法的符號引用
CONSTANT_InterfaceMethodref_info 11 接口中方法的符號引用
CONSTANT_NameAndType_info 12 字段或方法的符號引用
CONSTANT_MothodType_info 16 標(biāo)志方法類型
CONSTANT_MethodHandle_info 15 表示方法句柄
CONSTANT_InvokeDynamic_info 18 表示一個動態(tài)方法調(diào)用點(diǎn)

表 2 常量池?cái)?shù)據(jù)項(xiàng)目類型表

這14種常量結(jié)構(gòu)表開始的第一個字節(jié)都是一個u1類型的標(biāo)識位挟阻,其值就是表2中每項(xiàng)常量表類型所對應(yīng)的標(biāo)識列的值,代表當(dāng)前常量屬于哪種常量類型峭弟。這14種常量類型各自有自己不同的表結(jié)構(gòu)附鸽,詳情如表 3 所示。

常量 項(xiàng)目 類型 描述
CONSTANT_Utf8_info tag u1 值為1
length u2 UTF-8編碼的字符串占用的字節(jié)數(shù)
bytes u1 utf-8編碼的字符串
CONSTANT_Integer_info tag u1 值為3
bytes u4 按照Big-Endian存儲的int值
CONSTANT_Float_info tag u1 4
bytes u4 按照Big-Endian存儲的float值
CONSTANT_Long_info tag u1 5
bytes u8 按照Big-Endian存儲的long值
CONSTANT_Double_info tag u1 6
bytes u8 按照Big-Endian存儲的long值double值
CONSTANT_Class_info tag u1 7
index u2 指向全限定名常量項(xiàng)的索引
CONSTANT_String_info tag u1 8
index u2 指向字符串常量的索引
CONSTANT_Fieldref_info tag u1 9
index u2 指向聲明字段的類或接口描述符CONSTANT_Class_info的索引值
index u2 指向CONSTANT_NameAndType_info的索引值
CONSTANT_Methodref_info tag u1 10
index u2 指向聲明方法的類描述符CONSTANT_Class_info的索引值
index u2 指向CONSTANT_NameAndType_info的索引值
CONSTANT_InterfaceMethodref_info tag u1 11
index u2 指向聲明方法的接口描述符CONSTANT_Class_info的索引值
index u2 指向CONSTANT_NameAndType_info的索引值
CONSTANT_NameAndType_info tag u1 12
index u2 指向該字段或方法名稱常量的索引值
index u2 指向該字段或方法描述符常量的索引值
CONSTANT_MethodHandle_info tag u1 15
reference_kind u1 值必須1~9瞒瘸,它決定了方法句柄的的類型坷备。方法句柄類型的值表示方法句柄的字節(jié)碼行為
reference_index u2 對常量池的有效索引
CONSTANT_MethodType_info tag u1 16
description_index u2 對常量池中方法描述符的有效索引常量池在該處的索引必須是CONSTANT_Utf8_info的結(jié)構(gòu),表示方法的描述符情臭。
CONSTANT_InvokeDynamic_info tag u1 18
bootstap_method_attr_index u2 對當(dāng)前class文件中引導(dǎo)方法表的bootstap_methods[]數(shù)組的有效索引
name_and_type_index u2 對當(dāng)前常量池的有效索引省撑,常量池在此處必須是CONSTANT_NameAndType_info結(jié)構(gòu)赌蔑,表示方法名和方法描述。

表 3 常量池中14中常量的結(jié)構(gòu)總表

在表 3 中可以看到class文件所支持的所有的常量的結(jié)構(gòu)信息竟秫,另外由于class中的類名娃惯、方法、字段都要用CONSTANT_Utf8_info型的常量來描述名稱肥败,所以CONSTANT_Utf8_info的最大長度也是java中類名趾浅、方法名或字段的最大長度65535,如果超出這個最大長度馒稍,便會無法編譯潮孽。

訪問權(quán)限標(biāo)識

引用

在寫作本文的過程中引用了以下資料,為為在此深深謝過以下資料的作者筷黔。

  1. 《The Java Virtual Machine Specification》
  2. 《深入理解Java虛擬機(jī):JVM高級特性與最佳實(shí)踐/周志明著.——2版.——北京:機(jī)械工業(yè)出版社往史,2013.6》

關(guān)于

本項(xiàng)目和文檔中所用的內(nèi)容僅供學(xué)習(xí)和研究之用,轉(zhuǎn)載或引用時請指明出處佛舱。如果你對文檔有疑問或問題椎例,請?jiān)陧?xiàng)目中給我留言或發(fā)email到 weiwei02@vip.qq.com

from weiwei.wang 20170625

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
  • 序言:七十年代末,一起剝皮案震驚了整個濱河市请祖,隨后出現(xiàn)的幾起案子订歪,更是在濱河造成了極大的恐慌,老刑警劉巖肆捕,帶你破解...
    沈念sama閱讀 218,204評論 6 506
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件刷晋,死亡現(xiàn)場離奇詭異,居然都是意外死亡慎陵,警方通過查閱死者的電腦和手機(jī)眼虱,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 93,091評論 3 395
  • 文/潘曉璐 我一進(jìn)店門,熙熙樓的掌柜王于貴愁眉苦臉地迎上來席纽,“玉大人捏悬,你說我怎么就攤上這事∪筇荩” “怎么了过牙?”我有些...
    開封第一講書人閱讀 164,548評論 0 354
  • 文/不壞的土叔 我叫張陵,是天一觀的道長纺铭。 經(jīng)常有香客問我寇钉,道長,這世上最難降的妖魔是什么舶赔? 我笑而不...
    開封第一講書人閱讀 58,657評論 1 293
  • 正文 為了忘掉前任扫倡,我火速辦了婚禮,結(jié)果婚禮上顿痪,老公的妹妹穿的比我還像新娘镊辕。我一直安慰自己,他們只是感情好蚁袭,可當(dāng)我...
    茶點(diǎn)故事閱讀 67,689評論 6 392
  • 文/花漫 我一把揭開白布征懈。 她就那樣靜靜地躺著,像睡著了一般揩悄。 火紅的嫁衣襯著肌膚如雪卖哎。 梳的紋絲不亂的頭發(fā)上,一...
    開封第一講書人閱讀 51,554評論 1 305
  • 那天删性,我揣著相機(jī)與錄音亏娜,去河邊找鬼。 笑死蹬挺,一個胖子當(dāng)著我的面吹牛维贺,可吹牛的內(nèi)容都是我干的。 我是一名探鬼主播巴帮,決...
    沈念sama閱讀 40,302評論 3 418
  • 文/蒼蘭香墨 我猛地睜開眼溯泣,長吁一口氣:“原來是場噩夢啊……” “哼!你這毒婦竟也來了榕茧?” 一聲冷哼從身側(cè)響起垃沦,我...
    開封第一講書人閱讀 39,216評論 0 276
  • 序言:老撾萬榮一對情侶失蹤,失蹤者是張志新(化名)和其女友劉穎用押,沒想到半個月后肢簿,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體,經(jīng)...
    沈念sama閱讀 45,661評論 1 314
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡蜻拨,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 37,851評論 3 336
  • 正文 我和宋清朗相戀三年池充,在試婚紗的時候發(fā)現(xiàn)自己被綠了。 大學(xué)時的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片缎讼。...
    茶點(diǎn)故事閱讀 39,977評論 1 348
  • 序言:一個原本活蹦亂跳的男人離奇死亡纵菌,死狀恐怖,靈堂內(nèi)的尸體忽然破棺而出休涤,到底是詐尸還是另有隱情咱圆,我是刑警寧澤,帶...
    沈念sama閱讀 35,697評論 5 347
  • 正文 年R本政府宣布功氨,位于F島的核電站序苏,受9級特大地震影響,放射性物質(zhì)發(fā)生泄漏捷凄。R本人自食惡果不足惜忱详,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 41,306評論 3 330
  • 文/蒙蒙 一、第九天 我趴在偏房一處隱蔽的房頂上張望跺涤。 院中可真熱鬧匈睁,春花似錦监透、人聲如沸。這莊子的主人今日做“春日...
    開封第一講書人閱讀 31,898評論 0 22
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽。三九已至糯钙,卻和暖如春粪狼,著一層夾襖步出監(jiān)牢的瞬間,已是汗流浹背任岸。 一陣腳步聲響...
    開封第一講書人閱讀 33,019評論 1 270
  • 我被黑心中介騙來泰國打工再榄, 沒想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留,地道東北人享潜。 一個月前我還...
    沈念sama閱讀 48,138評論 3 370
  • 正文 我出身青樓困鸥,卻偏偏與公主長得像,于是被迫代替她去往敵國和親剑按。 傳聞我的和親對象是個殘疾皇子窝革,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 44,927評論 2 355

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

  • 字節(jié)碼查看工具:WinHex 前言 Java虛擬機(jī)實(shí)現(xiàn)語言無關(guān)性的基石就是Class文件Java虛擬機(jī)提供的語言無...
    zlcook閱讀 7,133評論 4 18
  • 相對于Java虛擬機(jī)的其他部分,這部分的內(nèi)容我們只需要搞清楚下面兩個方面的內(nèi)容: 1.無關(guān)性 2.Class文件的...
    beneke閱讀 787評論 0 2
  • 天氣漸漸暖了起來吕座,陽光變得和煦虐译,空氣中也會慢慢開始飄起柳絮,滿城繁花溫柔的撒著粉末吴趴。每當(dāng)這樣的時候漆诽,深吸一口氣,胸...
    素禧閱讀 242評論 0 0
  • 飄……娑羅的絮……沉寂的冬锣枝, 陰霾厢拭,隨風(fēng)轉(zhuǎn)著…… 卻始終散不去。拒絕著腐朽的疏影撇叁。 我記得供鸠, 影子在左, 我躲藏在...
    諳漓閱讀 325評論 0 0