從JVM設計者的角度來看.class文件結構,一文弄懂.class文件的身份地位

目錄

  • 本文相關虛擬機的命令

  • Class文件產生背景及重要地位

    • 【問題】只有Java語言編譯後的class文件才能在 JVM 裏面跑嗎?

    • class文件的地位

  • Class 類文件結構設計解析

    • 【問題】你會怎麼設計class文件?

本文相關虛擬機的命令

  1. 編寫Java源碼

Java源碼
  1. 編譯指令 javac xxx.java,得到.class文件

  2. hexdump -C filename可以查看二進制文件

.class 二進制文件
  1. 編譯後使用 javap -c 類名, 得到.class文件對應的虛擬機指令 class文件對應的虛擬機指令

class文件對應的虛擬機指令表

這裏先讓大家大致的看看.class文件和虛擬機指令的樣子,不會讓你有種“所愛隔山海”的感覺。

Class文件產生背景及重要地位

【問題】只有Java語言編譯後的class文件才能在 JVM 裏面跑嗎?

首先拋一個問題,是不是隻有Java語言編譯後的class文件才能在jvm中運行,也就是說其他的語言是否可以使用Java虛擬機作爲媒介?答案是:不是,可以的;只要符合JVM文件結構的規範,編譯後的文件均能運行,比如scala語言.scala結尾文件,可以編譯爲.class文件,可以在jvm中運行,哈哈哈,這裏寫的好生硬。

各種語言與JVM的愛恨情仇

如圖各種語言與JVM的愛恨情仇,只要你的語言經過自己的編譯器,最終能得到一個JVM需要的.class文件,那麼你就可以。

class文件的地位

  • Source: 源碼

  • Class: 字節碼

  • Runtime: 運行時

字節碼形態經由Classloader加載變成運行時形態(內存中)。

java 剛剛誕生的口號“一次編寫,到處運行",這是滿足開發人員對沖破平臺限制渴望的實現,這個很快就實現。然而設計者一開始發佈規範文檔的時候就是刻意把Java規範拆解成了《Java語言規範》和《Java虛擬機規範》,也就是說他們對虛擬機的野心不止於Java語言,他們未來的目標是衝破語言限制,現在也實現了,Scala,jRuby這些語言都可以運行在Java虛擬機上面。隨着平臺(windows,linux,unix)基本穩定,而語言日新月異,日後JAVA“語言無關”的優勢可能會超過“平臺無關”的優勢!

實現語言無關的關鍵就是虛擬機和字節碼存儲格式。可以理解成虛擬機給你提供一個接口,你只需要按照他指定的格式傳class文件給他,他便可以運行你的代碼,所以關鍵就是這個class文件。虛擬機不關心你的項目使用什麼語言進行代碼實現,最後你只需要按照他想要的class格式編譯成class文件傳給他,就可以成功運行在虛擬機上面。我說的夠清楚了吧老弟?

Class 類文件結構設計解析

class 文件是一組以8位字節爲基礎單位的二進制流,中間沒有任何分隔符,正是因爲沒有任何分隔符所以class文件裏面的數據項在順序和數量上面是嚴格限定的,每個字節的含義,長度,先後順序,都不允許改變。具體class文件內容看圖。

class文件採用的是一種類似於C語言結構體的僞結構來存儲數據,本質就是一張表,如圖所示:

.class 二進制文件
class文件對應內容

【問題】你會怎麼設計class文件?

首先拋出一個問題,JVM一開始就是服務Java的,拿Java語言來舉例子,如果你是設計者,你將你的Java源碼編譯成class文件,你會怎麼設計這個class文件?

思路:轉換成容易理解的實現,知道Java的,一般都知道xml文件,一個JavaBean完全可以轉化爲用xml這種描述性語言來表示,原因是xml是指定好了協議,你的Java要變成 xml 就要按照我的協議來辦事,用 xml 描述一個學生對象如下:

xml 表示的Java對象

協議的話其實就很能理解,你的class是一個十六進制文件,那麼就必須制定自己的協議啊,使得你的十六進制描述的東西可以轉化爲 JVM 可以理解的虛擬機指令,也就是你的 “xx” 這幾個字母是爲了告訴虛擬機幹啥,“oo”這幾個字母是想告訴虛擬機幹啥,“xxoo”又是表示啥,這裏先看看實際的JVM指令以及和class文件對應關係(現在的 JVM 指令有255個大約)

JVM指令表

轉化:有了思路就好辦了,轉化一下,將 JAVA 源碼轉化爲 CLASS 文件,來看看具體怎麼轉化:

  1. 一個Java類對應一個class文件(有可能是多個,如果類裏面有內部類),裏面有哪些東西?肯定不能丟東西嘛,這是最基本的要求,如果人家明明寫的是“你綠了我嗎”,你給搞成了“你綠了我”,那這心情起伏還是蠻大的哈。

  2. Java類裏面的東西你怎麼剖析,怎麼設計存儲?

  • 簡單解剖一下,class文件可能是Java中的class類,也可能是接口,一個class所表示的裏面還可能不止一個類和接口,得區分一下吧?來,敲黑板劃重點,大膽設計就是接口類型集合,普通類集合,還不止一個?再加兩個字段接口個數,類個數,一切都是這麼的完美,往class文件裏面找,我去都能找到,OK,我是天才,下一個。

  • Java裏面有屬性,有方法,有常量,有字段,怎麼破?繼續嘛,集合搞起來,個數存起來,最終得到了上面圖裏面的表結構的class文件。

再來回顧一下class文件內容:

  1. Java類裏面有什麼東西,class文件應該存儲些什麼東西?

  • 兩種數據類型:無符號數和表無符號數屬於基本數據類型(Java類中也有基本數據類型),以 u1,u2,u4,u8這種來代表1個字節,2個字節,4個字節,8個字節的無符號數,可以用來描述數字,索引引用,數量值或者字符串值。就跟Java類中的對象引用類型一樣,對象屬性可以是基本數據類型(對應U1,U2無符號數),也可以是其他的對象(對應其他的表),Java工程項目中參數實體通常以"_Param"結尾(class文件的表都習慣以“_info”結尾)

  • 上圖中的順序,就是Class文件嚴格要求的順序

  • 各個計數器主要是用來描述表裏面數據個數,例如方法計數器的值是methods_count,代表方法表method——info裏面有“methods_count”個方法

  • 整理一下,表結構用C語言表示類似下面的僞代碼(忽略idea報錯的紅線)

class文件代碼表示

完結撒花了?這裏我是從宏觀上講解了下.class文件,下期進行.class類文件結構詳細解析,以及字節碼指令的剖析,本篇只是個開胃菜,下一篇內容纔是主菜。

有收穫的老鐵不妨點個右下角“在看”,語言風格有點沙雕見諒,另外Java類在JVM裏面的生命週期可以看我上一篇內容:Java類的生命週期,不懂這個都不好意思和別人說我是搞JAVA的

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章