LetsCoding.cn

          天地之間有桿秤,拿秤砣砸老百姓。

          短小精悍的虛擬機:JVM基本結構和功能介紹

          歡迎來到“Under The Hood”第一期。本期,我將給出JVM的基本結構和功能介紹。

          什么是JVM?為什么要有它?

          JVM(Java虛擬機)是一個運行已編譯Java程序的抽象計算機。之所以說是”虛擬“的,是因為它基于“真正”的硬件平臺和操作系統,一般以軟件的形式實現。所有的Java程序都為JVM而編譯。因此,在特定平臺上運行已編譯Java程序之前,該平臺的JVM必須先要被實現。

          JVM在Java的跨平臺特性中,起著中間人的角色。它在已編譯Java程序與底層硬件平臺和操作系統之間,提供一個抽象層。JVM對Java的可移植性非常關鍵,因為,已編譯Java程序運行在JVM之上,并獨立于底層JVM的具體實現。

          那么,是什么導致JVM的短小精悍?當被實現成軟件時,JMV很小巧。它被設計成這樣,是為了讓它能夠適用于盡可能多的地方,比如機頂盒,手機和個人電腦。JVM很精悍,是因為它的野心。”無處不在!“是它的戰斗口號。它想要無處不在,并且Java程序”一次編寫,到處運行“的程度說明了它的成功。

          Java字節碼

          Java程序被編譯成一種叫做字節碼的東東。JVM執行Java字節碼,所以字節碼可以被認為是JVM的機器語言。Java編譯器讀取Java源文件,把它翻譯成Java字節碼并保存到類文件(.class文件)中。編譯器會為源碼中的每一個類生成一個類文件。

          對JVM來說,字節碼流就是指令序列。每條指令包含一個單字節的操作碼和零個或多個操作數。操作碼告訴JVM要執行的操作。如果JVM需要除操作碼之外更多的信息去執行一項操作,那么,需要的信息作為操作數,緊跟在操作碼之后。

          每個字節碼都有一個助記符,它可被當作JVM的匯編語言。例如,有個指令會讓JVM把0壓到堆棧中。該指令的助記符是iconst_0,字節碼值是0×60。該指令沒有操作數。另一個指令讓程序的執行在內存中無條件向前向后跳轉。這個指令需要一個操作數,它是一個指明從當前內存地址開始的2字節無符號偏移量。通過把偏移量加到當前內存地址,JVM可以獲得要跳轉的目標內存地址。該指令的助記符是goto,它的字節碼值是0xa7。

          虛擬部分

          JVM的“虛擬硬件”可以分為四個部分:寄存器組,棧區,垃圾收集堆和方法區。這些部分很抽象,就像由它們組成的虛擬機一樣;但是它們必須在每個JVM的實現中,以某種形式存在。

          JVM中地址的是32位(4字節)的,因此,JVM可以處理4GB(2的32次方)的內存。棧區,垃圾收集堆和方法區處在這4GB內存中的某個地方,至于它們的具體內存地址,這取決于每個特定JVM的實現者。

          JVM中一個字(word)的長度是32位的。JVM中有少數幾個原始數據類型:byte(8位),short(16位),int(32位),long(64位),float(32位),double(64位),char(16位)。除了無符號Unicode字符char之外,其他6種數字類型都是有符號的。這些類型可以方便的映射到Java程序員可用的數據類型。另一個原始類型是對象句柄,它是一個指向堆中對象的32位地址。

          由于包含字節碼,方法區以字節邊界對齊。棧和垃圾收集堆以字(32位)邊界對齊1

          寄存器:我少我自豪

          JVM有1個程序計數器(counter)和3個管理棧的寄存器(register)。它只有很少的寄存器,是因為JVM字節碼指令主要操作棧區。這種面向棧的設計,使得JVM指令集和JVM實現很小巧。

          JVM使用程序計數器(也叫pc寄存器),跟蹤當前執行指令的內存位置。另外3個寄存器(optop寄存器,frame寄存器和vars寄存器)指向當前執行方法棧幀上不同的部位。執行方法的棧幀持有特定方法調用的狀態(本地變量,即時計算結果等)。

          方法區和程序計數器

          方法區是字節碼呆的地方。程序計數器跟蹤執行線程。當前字節碼指令執行后,程序計數器會包含下一條執行指令的地址:一條指令執行之后,JVM把程序計數器設置為緊跟上一條指令的指令地址,除非上一條指令具體指明一次跳轉。

          Java棧和相關寄存器

          Java棧用來保存字節碼指令的參數和執行結果,給方法傳遞參數和返回結果,保存每個方法調用的狀態。方法調用的狀態被稱為調用棧幀。var寄存器,frame寄存器和optop寄存器指向當前棧幀的不同部位。

          Java棧幀有3個區:本地變量,執行環境和操作數棧。本地變量區,包含當前方法調用中使用的所有本地變量。它由vars寄存器指向。執行環境區用來維護棧區本身的操作。它被frame寄存器指向。操作數區用來作為字碼指令的工作區。正是在這里,存放著字節碼指令的參數和其返回結果。操作數棧區的頂部被optop寄存器指向。

          執行環境通常夾在本地變量和操作數棧中間。當前執行方法的操作數棧總是在棧區的最上面,所以optop寄存器總是指向整個Java棧的頂部。

          垃圾收集堆

          堆是Java對象生存的地方。任何時候,你用new操作符分配的內存,都來自堆中。Java語言不允許你直接釋放分配的內存。運行時環境會跟蹤堆上每個對象的引用,自動釋放那些不被引用的對象所占據的內存,這個過程被稱為垃圾收集。

          參考

          1. 關于內存對齊方式,請參考Data alignment: Straighten up and fly right

          本文譯自:The lean, mean, virtual machine

          原創文章,轉載請注明: 轉載自LetsCoding.cn
          本文鏈接地址: 短小精悍的虛擬機:JVM基本結構和功能介紹

          posted on 2014-05-17 21:50 Rolandz 閱讀(1615) 評論(0)  編輯  收藏 所屬分類: 編程實踐

          導航

          統計

          留言簿(1)

          隨筆分類(12)

          隨筆檔案(19)

          積分與排名

          最新評論

          閱讀排行榜

          評論排行榜

          主站蜘蛛池模板: 金山区| 四川省| 嘉荫县| 西城区| 蓬安县| 喀喇| 甘德县| 临武县| 温州市| 温泉县| 凤城市| 瑞金市| 米林县| 龙陵县| 奉贤区| 南华县| 武义县| 萨迦县| 通道| 大港区| 文山县| 临洮县| 乌恰县| 京山县| 吉木乃县| 五莲县| 莱州市| 武夷山市| 随州市| 万载县| 竹溪县| 广东省| 云阳县| 册亨县| 苍山县| 漳平市| 九龙城区| 富民县| 湖南省| 株洲县| 双辽市|