JVM基本結構和功能介紹

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,字節碼值是0x60。該指令沒有操作數。另一個指令讓程序的執行在內存中無條件向前向後跳轉。這個指令需要一個操作數,它是一個指明從當前內存地址開始的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語言不允許你直接釋放分配的內存。運行時環境會跟蹤堆上每個對象的引用,自動釋放那些不被引用的對象所佔據的內存,這個過程被稱為垃圾收集。


分享到:


相關文章: