<rt id="bn8ez"></rt>
<label id="bn8ez"></label>

  • <span id="bn8ez"></span>

    <label id="bn8ez"><meter id="bn8ez"></meter></label>

    weidagang2046的專欄

    物格而后知致
    隨筆 - 8, 文章 - 409, 評論 - 101, 引用 - 0
    數(shù)據(jù)加載中……

    Java虛擬機的深入研究

    作者:劉學超

    1  Java技術與Java虛擬機

    說起Java,人們首先想到的是Java編程語言,然而事實上,Java是一種技術,它由四方面組成: Java編程語言、Java類文件格式、Java虛擬機和Java應用程序接口(Java API)。它們的關系如下圖所示:

    圖1  Java四個方面的關系

    運行期環(huán)境代表著Java平臺,開發(fā)人員編寫Java代碼(.java文件),然后將之編譯成字節(jié)碼(.class文件)。最后字節(jié)碼被裝入內存,一旦字節(jié)碼進入虛擬機,它就會被解釋器解釋執(zhí)行,或者是被即時代碼發(fā)生器有選擇的轉換成機器碼執(zhí)行。從上圖也可以看出Java平臺由Java虛擬機和Java應用程序接口搭建,Java語言則是進入這個平臺的通道,用Java語言編寫并編譯的程序可以運行在這個平臺上。這個平臺的結構如下圖所示:

    在Java平臺的結構中, 可以看出,Java虛擬機(JVM) 處在核心的位置,是程序與底層操作系統(tǒng)和硬件無關的關鍵。它的下方是移植接口,移植接口由兩部分組成:適配器和Java操作系統(tǒng), 其中依賴于平臺的部分稱為適配器;JVM 通過移植接口在具體的平臺和操作系統(tǒng)上實現(xiàn);在JVM 的上方是Java的基本類庫和擴展類庫以及它們的API, 利用Java API編寫的應用程序(application) 和小程序(Java applet) 可以在任何Java平臺上運行而無需考慮底層平臺, 就是因為有Java虛擬機(JVM)實現(xiàn)了程序與操作系統(tǒng)的分離,從而實現(xiàn)了Java 的平臺無關性。

    那么到底什么是Java虛擬機(JVM)呢?通常我們談論JVM時,我們的意思可能是:

    1. 對JVM規(guī)范的的比較抽象的說明;
    2. 對JVM的具體實現(xiàn);
    3. 在程序運行期間所生成的一個JVM實例。

    對JVM規(guī)范的的抽象說明是一些概念的集合,它們已經(jīng)在書《The Java Virtual Machine Specification》(《Java虛擬機規(guī)范》)中被詳細地描述了;對JVM的具體實現(xiàn)要么是軟件,要么是軟件和硬件的組合,它已經(jīng)被許多生產(chǎn)廠商所實現(xiàn),并存在于多種平臺之上;運行Java程序的任務由JVM的運行期實例單個承擔。在本文中我們所討論的Java虛擬機(JVM)主要針對第三種情況而言。它可以被看成一個想象中的機器,在實際的計算機上通過軟件模擬來實現(xiàn),有自己想象中的硬件,如處理器、堆棧、寄存器等,還有自己相應的指令系統(tǒng)。

    JVM在它的生存周期中有一個明確的任務,那就是運行Java程序,因此當Java程序啟動的時候,就產(chǎn)生JVM的一個實例;當程序運行結束的時候,該實例也跟著消失了。下面我們從JVM的體系結構和它的運行過程這兩個方面來對它進行比較深入的研究。

    2  Java虛擬機的體系結構

    剛才已經(jīng)提到,JVM可以由不同的廠商來實現(xiàn)。由于廠商的不同必然導致JVM在實現(xiàn)上的一些不同,然而JVM還是可以實現(xiàn)跨平臺的特性,這就要歸功于設計JVM時的體系結構了。

    我們知道,一個JVM實例的行為不光是它自己的事,還涉及到它的子系統(tǒng)、存儲區(qū)域、數(shù)據(jù)類型和指令這些部分,它們描述了JVM的一個抽象的內部體系結構,其目的不光規(guī)定實現(xiàn)JVM時它內部的體系結構,更重要的是提供了一種方式,用于嚴格定義實現(xiàn)時的外部行為。每個JVM都有兩種機制,一個是裝載具有合適名稱的類(類或是接口),叫做類裝載子系統(tǒng);另外的一個負責執(zhí)行包含在已裝載的類或接口中的指令,叫做運行引擎。每個JVM又包括方法區(qū)、堆、Java棧、程序計數(shù)器和本地方法棧這五個部分,這幾個部分和類裝載機制與運行引擎機制一起組成的體系結構圖為:

    圖3  JVM的體系結構

    JVM的每個實例都有一個它自己的方法域和一個堆,運行于JVM內的所有的線程都共享這些區(qū)域;當虛擬機裝載類文件的時候,它解析其中的二進制數(shù)據(jù)所包含的類信息,并把它們放到方法域中;當程序運行的時候,JVM把程序初始化的所有對象置于堆上;而每個線程創(chuàng)建的時候,都會擁有自己的程序計數(shù)器和Java棧,其中程序計數(shù)器中的值指向下一條即將被執(zhí)行的指令,線程的Java棧則存儲為該線程調用Java方法的狀態(tài);本地方法調用的狀態(tài)被存儲在本地方法棧,該方法棧依賴于具體的實現(xiàn)。

    下面分別對這幾個部分進行說明。

    執(zhí)行引擎處于JVM的核心位置,在Java虛擬機規(guī)范中,它的行為是由指令集所決定的。盡管對于每條指令,規(guī)范很詳細地說明了當JVM執(zhí)行字節(jié)碼遇到指令時,它的實現(xiàn)應該做什么,但對于怎么做卻言之甚少。Java虛擬機支持大約248個字節(jié)碼。每個字節(jié)碼執(zhí)行一種基本的CPU運算,例如,把一個整數(shù)加到寄存器,子程序轉移等。Java指令集相當于Java程序的匯編語言。

    Java指令集中的指令包含一個單字節(jié)的操作符,用于指定要執(zhí)行的操作,還有0個或多個操作數(shù),提供操作所需的參數(shù)或數(shù)據(jù)。許多指令沒有操作數(shù),僅由一個單字節(jié)的操作符構成。

    虛擬機的內層循環(huán)的執(zhí)行過程如下: 
    do{ 
    取一個操作符字節(jié); 
    根據(jù)操作符的值執(zhí)行一個動作; 
    }while(程序未結束)
    

    由于指令系統(tǒng)的簡單性,使得虛擬機執(zhí)行的過程十分簡單,從而有利于提高執(zhí)行的效率。指令中操作數(shù)的數(shù)量和大小是由操作符決定的。如果操作數(shù)比一個字節(jié)大,那么它存儲的順序是高位字節(jié)優(yōu)先。例如,一個16位的參數(shù)存放時占用兩個字節(jié),其值為:

    第一個字節(jié)*256+第二個字節(jié)字節(jié)碼。

    指令流一般只是字節(jié)對齊的。指令tableswitch和lookup是例外,在這兩條指令內部要求強制的4字節(jié)邊界對齊。

    對于本地方法接口,實現(xiàn)JVM并不要求一定要有它的支持,甚至可以完全沒有。Sun公司實現(xiàn)Java本地接口(JNI)是出于可移植性的考慮,當然我們也可以設計出其它的本地接口來代替Sun公司的JNI。但是這些設計與實現(xiàn)是比較復雜的事情,需要確保垃圾回收器不會將那些正在被本地方法調用的對象釋放掉。

    Java的堆是一個運行時數(shù)據(jù)區(qū),類的實例(對象)從中分配空間,它的管理是由垃圾回收來負責的:不給程序員顯式釋放對象的能力。Java不規(guī)定具體使用的垃圾回收算法,可以根據(jù)系統(tǒng)的需求使用各種各樣的算法。

    Java方法區(qū)與傳統(tǒng)語言中的編譯后代碼或是Unix進程中的正文段類似。它保存方法代碼(編譯后的java代碼)和符號表。在當前的Java實現(xiàn)中,方法代碼不包括在垃圾回收堆中,但計劃在將來的版本中實現(xiàn)。每個類文件包含了一個Java類或一個Java界面的編譯后的代碼。可以說類文件是Java語言的執(zhí)行代碼文件。為了保證類文件的平臺無關性,Java虛擬機規(guī)范中對類文件的格式也作了詳細的說明。其具體細節(jié)請參考Sun公司的Java虛擬機規(guī)范。

    Java虛擬機的寄存器用于保存機器的運行狀態(tài),與微處理器中的某些專用寄存器類似。Java虛擬機的寄存器有四種:

    1. pc: Java程序計數(shù)器;
    2. optop: 指向操作數(shù)棧頂端的指針;
    3. frame: 指向當前執(zhí)行方法的執(zhí)行環(huán)境的指針;。
    4. vars: 指向當前執(zhí)行方法的局部變量區(qū)第一個變量的指針。

    在上述體系結構圖中,我們所說的是第一種,即程序計數(shù)器,每個線程一旦被創(chuàng)建就擁有了自己的程序計數(shù)器。當線程執(zhí)行Java方法的時候,它包含該線程正在被執(zhí)行的指令的地址。但是若線程執(zhí)行的是一個本地的方法,那么程序計數(shù)器的值就不會被定義。

    Java虛擬機的棧有三個區(qū)域:局部變量區(qū)、運行環(huán)境區(qū)、操作數(shù)區(qū)。

    局部變量區(qū)

    每個Java方法使用一個固定大小的局部變量集。它們按照與vars寄存器的字偏移量來尋址。局部變量都是32位的。長整數(shù)和雙精度浮點數(shù)占據(jù)了兩個局部變量的空間,卻按照第一個局部變量的索引來尋址。(例如,一個具有索引n的局部變量,如果是一個雙精度浮點數(shù),那么它實際占據(jù)了索引n和n+1所代表的存儲空間)虛擬機規(guī)范并不要求在局部變量中的64位的值是64位對齊的。虛擬機提供了把局部變量中的值裝載到操作數(shù)棧的指令,也提供了把操作數(shù)棧中的值寫入局部變量的指令。

    運行環(huán)境區(qū)

    在運行環(huán)境中包含的信息用于動態(tài)鏈接,正常的方法返回以及異常捕捉。

    動態(tài)鏈接

    運行環(huán)境包括對指向當前類和當前方法的解釋器符號表的指針,用于支持方法代碼的動態(tài)鏈接。方法的class文件代碼在引用要調用的方法和要訪問的變量時使用符號。動態(tài)鏈接把符號形式的方法調用翻譯成實際方法調用,裝載必要的類以解釋還沒有定義的符號,并把變量訪問翻譯成與這些變量運行時的存儲結構相應的偏移地址。動態(tài)鏈接方法和變量使得方法中使用的其它類的變化不會影響到本程序的代碼。

    正常的方法返回

    如果當前方法正常地結束了,在執(zhí)行了一條具有正確類型的返回指令時,調用的方法會得到一個返回值。執(zhí)行環(huán)境在正常返回的情況下用于恢復調用者的寄存器,并把調用者的程序計數(shù)器增加一個恰當?shù)臄?shù)值,以跳過已執(zhí)行過的方法調用指令,然后在調用者的執(zhí)行環(huán)境中繼續(xù)執(zhí)行下去。

    異常捕捉

    異常情況在Java中被稱作Error(錯誤)或Exception(異常),是Throwable類的子類,在程序中的原因是:①動態(tài)鏈接錯,如無法找到所需的class文件。②運行時錯,如對一個空指針的引用。程序使用了throw語句。

    當異常發(fā)生時,Java虛擬機采取如下措施:

    • 檢查與當前方法相聯(lián)系的catch子句表。每個catch子句包含其有效指令范圍,能夠處理的異常類型,以及處理異常的代碼塊地址。
    • 與異常相匹配的catch子句應該符合下面的條件:造成異常的指令在其指令范圍之內,發(fā)生的異常類型是其能處理的異常類型的子類型。如果找到了匹配的catch子句,那么系統(tǒng)轉移到指定的異常處理塊處執(zhí)行;如果沒有找到異常處理塊,重復尋找匹配的catch子句的過程,直到當前方法的所有嵌套的catch子句都被檢查過。
    • 由于虛擬機從第一個匹配的catch子句處繼續(xù)執(zhí)行,所以catch子句表中的順序是很重要的。因為Java代碼是結構化的,因此總可以把某個方法的所有的異常處理器都按序排列到一個表中,對任意可能的程序計數(shù)器的值,都可以用線性的順序找到合適的異常處理塊,以處理在該程序計數(shù)器值下發(fā)生的異常情況。
    • 如果找不到匹配的catch子句,那么當前方法得到一個"未截獲異常"的結果并返回到當前方法的調用者,好像異常剛剛在其調用者中發(fā)生一樣。如果在調用者中仍然沒有找到相應的異常處理塊,那么這種錯誤將被傳播下去。如果錯誤被傳播到最頂層,那么系統(tǒng)將調用一個缺省的異常處理塊。

    操作數(shù)棧區(qū)

    機器指令只從操作數(shù)棧中取操作數(shù),對它們進行操作,并把結果返回到棧中。選擇棧結構的原因是:在只有少量寄存器或非通用寄存器的機器(如Intel486)上,也能夠高效地模擬虛擬機的行為。操作數(shù)棧是32位的。它用于給方法傳遞參數(shù),并從方法接收結果,也用于支持操作的參數(shù),并保存操作的結果。例如,iadd指令將兩個整數(shù)相加。相加的兩個整數(shù)應該是操作數(shù)棧頂?shù)膬蓚€字。這兩個字是由先前的指令壓進堆棧的。這兩個整數(shù)將從堆棧彈出、相加,并把結果壓回到操作數(shù)棧中。

    每個原始數(shù)據(jù)類型都有專門的指令對它們進行必須的操作。每個操作數(shù)在棧中需要一個存儲位置,除了long和double型,它們需要兩個位置。操作數(shù)只能被適用于其類型的操作符所操作。例如,壓入兩個int類型的數(shù),如果把它們當作是一個long類型的數(shù)則是非法的。在Sun的虛擬機實現(xiàn)中,這個限制由字節(jié)碼驗證器強制實行。但是,有少數(shù)操作(操作符dupe和swap),用于對運行時數(shù)據(jù)區(qū)進行操作時是不考慮類型的。

    本地方法棧,當一個線程調用本地方法時,它就不再受到虛擬機關于結構和安全限制方面的約束,它既可以訪問虛擬機的運行期數(shù)據(jù)區(qū),也可以使用本地處理器以及任何類型的棧。例如,本地棧是一個C語言的棧,那么當C程序調用C函數(shù)時,函數(shù)的參數(shù)以某種順序被壓入棧,結果則返回給調用函數(shù)。在實現(xiàn)Java虛擬機時,本地方法接口使用的是C語言的模型棧,那么它的本地方法棧的調度與使用則完全與C語言的棧相同。

    3  Java虛擬機的運行過程

    上面對虛擬機的各個部分進行了比較詳細的說明,下面通過一個具體的例子來分析它的運行過程。

    虛擬機通過調用某個指定類的方法main啟動,傳遞給main一個字符串數(shù)組參數(shù),使指定的類被裝載,同時鏈接該類所使用的其它的類型,并且初始化它們。例如對于程序:

    class HelloApp 
    {
    	public static void main(String[] args) 
    	{
    		System.out.println("Hello World!"); 
    		for (int i = 0; i < args.length; i++ )
    		{
    			System.out.println(args[i]);
    		}
    	}
    }
    

    編譯后在命令行模式下鍵入: java HelloApp run virtual machine

    將通過調用HelloApp的方法main來啟動java虛擬機,傳遞給main一個包含三個字符串"run"、"virtual"、"machine"的數(shù)組。現(xiàn)在我們略述虛擬機在執(zhí)行HelloApp時可能采取的步驟。

    開始試圖執(zhí)行類HelloApp的main方法,發(fā)現(xiàn)該類并沒有被裝載,也就是說虛擬機當前不包含該類的二進制代表,于是虛擬機使用ClassLoader試圖尋找這樣的二進制代表。如果這個進程失敗,則拋出一個異常。類被裝載后同時在main方法被調用之前,必須對類HelloApp與其它類型進行鏈接然后初始化。鏈接包含三個階段:檢驗,準備和解析。檢驗檢查被裝載的主類的符號和語義,準備則創(chuàng)建類或接口的靜態(tài)域以及把這些域初始化為標準的默認值,解析負責檢查主類對其它類或接口的符號引用,在這一步它是可選的。類的初始化是對類中聲明的靜態(tài)初始化函數(shù)和靜態(tài)域的初始化構造方法的執(zhí)行。一個類在初始化之前它的父類必須被初始化。整個過程如下:

    圖4:虛擬機的運行過程

    4  結束語

    本文通過對JVM的體系結構的深入研究以及一個Java程序執(zhí)行時虛擬機的運行過程的詳細分析,意在剖析清楚Java虛擬機的機理。

    Solaris論壇

     

     

    常見問答

    下載中心

    產(chǎn)品簡介

     

    轉自:http://gceclub.sun.com.cn/staticcontent/html/2004-04-09/jvm.html

    posted on 2005-05-11 01:00 weidagang2046 閱讀(165) 評論(0)  編輯  收藏 所屬分類: Java

    主站蜘蛛池模板: 日本v片免费一区二区三区| 色网站在线免费观看| 亚洲午夜成人精品无码色欲| 瑟瑟网站免费网站入口| 91精品国产免费| 国产精品va无码免费麻豆| 亚洲Av无码专区国产乱码DVD| 亚洲人成网亚洲欧洲无码| 久青草视频在线观看免费| 美女被免费喷白浆视频| 亚洲日本乱码在线观看| 亚洲成AV人影片在线观看| 日韩人妻无码精品久久免费一| 日韩在线看片免费人成视频播放| 亚洲AV无码久久| 高潮内射免费看片| 成人午夜性A级毛片免费| 亚洲综合国产精品| 久久免费香蕉视频| 免费人妻无码不卡中文字幕18禁| 亚洲色偷偷偷网站色偷一区| 日本一区二区三区免费高清在线 | 久久免费香蕉视频| 在线免费观看国产视频| 久久精品亚洲精品国产色婷| 亚洲免费日韩无码系列| 日韩免费一级毛片| 国产精品高清视亚洲一区二区| 日本免费大黄在线观看| 亚洲中文字幕无码爆乳AV| 精品久久久久久亚洲中文字幕| 日韩免费一区二区三区在线播放| 亚洲狠狠久久综合一区77777| 本道天堂成在人线av无码免费 | 免费在线观看亚洲| 亚洲中文字幕无码中文字| 1000部啪啪未满十八勿入免费| 亚洲色大成网站WWW久久九九| 国产免费伦精品一区二区三区| 亚洲成A人片在线观看无码3D| 337P日本欧洲亚洲大胆精品|