Java查漏系列(1)——JVM

來源:互聯網
上載者:User

一年多的時間沒搞過java了,最近在學習hadoop,所以想把java再撿一撿,以前主要關注java的文法和api等,很少關注底層記憶體等,所以現在找時間把這塊撿撿。

JVM,全稱java virtual machine,也就是java虛擬機器,望文生義的解釋就是在電腦上面再虛擬出一個執行java程式的電腦。具體一點說,jvm可以被看成一個想象中的機器,在實際的電腦上通過軟體類比來實現,有自己想象中的硬體,如處理器、堆棧、寄存器等,還有自己相應的指令系統。JVM在它的生存周期中有一個明確的任務,那就是運行Java程式,因此當Java程式啟動的時候,就產生JVM的一個執行個體;當程式運行結束的時候,該執行個體也跟著消失了。下面分別從JVM在系統中所處的位置、JVM的體繫結構和JVM的運行過程三個方面來對JVM做一下介紹。

1.JVM在系統中的位置

首先,從宏觀上看,JVM就是運行於具體作業系統上面的一個軟體,如所示:

在整個java平台中,JVM是介於java應用程式與具體作業系統之間的一個組件,JVM在java平台中的位置如所示:

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

2.JVM體繫結構

每個JVM都有兩種機制,一個是裝載具有合適名稱的類(類或是介面),叫做Class Loader;另外的一個負責執行包含在已裝載的類或介面中的指令,叫做Execution Engine。每個JVM又包括Method Area、Heap、 Stack、PC Register和Native
Method Stack這五個部分,這幾個部分和類裝載機制與運行引擎機制一起組成的體繫結構圖為:

該圖參考了網上廣為流傳的JVM構成圖,從這個圖中可以看出,整個JVM分為以下四個部分:

1)Class Loader(類裝載器)

類載入器的作用是載入類檔案到記憶體,比如編寫一個HelloWord.java程式,然後通過javac編譯成class檔案,那怎麼才能載入到記憶體中被執行呢?Class Loader承擔的就是這個責任,並不是隨便建立一個.class檔案就能被載入的,Class Loader載入的class檔案是有格式要求的,另外,Class Loader只管載入,只要符合檔案結構就載入,至於說能不能運行,則不是它負責的,那是由ExecutionEngine負責的。

2)Execution Engine(執行引擎)

執行引擎也叫做解譯器(Interpreter),負責解釋命令,提交作業系統執行。執行引擎處於JVM的核心位置,在Java虛擬機器規範中,它的行為是由指令集所決定的。Java指令集相當於Java程式的組合語言。Java指令集中的指令包含一個單位元組的操作符,用於指定要執行的操作,還有0個或多個運算元,提供操作所需的參數或資料。許多指令沒有運算元,僅由一個單位元組的操作符構成。

虛擬機器的內層迴圈的執行過程如下:

do{取一個操作符位元組;根據操作符的值執行一個動作;}while(程式未結束);

由於指令系統的簡單性,使得虛擬機器執行的過程十分簡單,從而有利於提高執行的效率。

3)Native Interface(本地介面)

本地介面的作用是融合不同的程式設計語言為Java所用,它的初衷是融合C/C++程式,Java誕生的時候是C/C++橫行的時候,要想立足,必須有一個聰明的、睿智的調用C/C++程式,於是就在記憶體中專門開闢了一塊地區處理標記為native的代碼,它的具體做法是Native MethodStack中登記native方法,在ExecutionEngine執行時載入nativelibraies。目前該方法使用的是越來越少了,除非是與硬體有關的應用,比如通過Java程式驅動印表機,或者Java系統管理生產裝置,在企業級應用中已經比較少見,因為現在的異構領域間的通訊很發達,比如可以使用Socket通訊,也可以使用Web
Service等等,不多做介紹。

4)Runtime Data Area(運行時資料區)

運行時資料區是整個JVM的重點,我們所有寫的程式都被載入到這裡,之後才開始運行,Java生態系統如此的繁榮,得益於該地區的優良自治。其中,Method Area和Heap是基於JVM執行個體的,即JVM的每個執行個體都有一個它自己的方法域和一個堆,運行於JVM內的所有的線程都共用這些地區,當虛擬機器裝載類檔案的時候,它解析其中的位元據所包含的類資訊,並把它們放到方法域中;當程式啟動並執行時候,JVM把程式初始化的所有對象置於堆上。PC
Register和Stack是基於線程的,即每個線程建立的時候,都會擁有自己的程式計數器和 Java棧,其中程式計數器中的值指向下一條即將被執行的指令,線程的Java棧則儲存為該線程調用Java方法的狀態。本地方法調用的狀態被儲存在NativeMethod  Stack,該方法棧依賴於具體的實現。

由於運行時資料區是整個JVM的重點,所以下一節詳細介紹。

3.JVM運行過程

java源檔案經過java編譯器編譯產生位元組碼檔案(.class),位元組碼檔案要能夠在JVM中執行,需要經過以下三個步驟:裝載、連結、初始化。下面分別對這三個步驟進行說明:

裝載:類的裝載是通過類裝載器來完成的,類裝載器需要完成的功能是定義一個java類,即把java位元組碼轉換成JVM中的java.lang.class類的對象。所有的java類在JVM中的表現形式都是java.lang.class類的對象。

連結:java類的連結指的是將java類的二進位代碼合并到JVM的運行狀態之中的過程。在連結之前,這個類必須被成功載入。類的連結包括驗證、準備和解析等幾個步驟。驗證用來確保java類的二進位表示在結構上是完全正確的,如果驗證過程出現錯誤的話,會拋出java.lang.VerifyError錯誤。準備過程是建立java類中的靜態域,並將這些域設為預設值,準備過程並不會執行代碼。在一個java類中會包含對其它類或介面的形式引用,包括它的父類、所實現的介面、方法的形式參數和傳回值的java類等,解析的過程就是確保這些被引用的類能被正確的找到,解析的過程可能會導致其它的java類被載入。

初始化:當一個java類第一次被真正使用到的時候,JVM會進行該類的初始化操作,初始化過程的主要操作是執行靜態代碼塊和初始化靜態域。在一個類被初始化之前,它的直接父類也需要被初始化。

下面通過一個例子來說明JVM的運行過程:

class HelloApp {public static int x = 10;public static void main(String[] args) {System.out.println(x);}static{x = 30;}}

其執行流程如下:

開始試圖執行類HelloApp的main方法,發現該類並沒有被裝載,也就是說虛擬機器當前不包含該類的二進位代表,於是虛擬機器使用 ClassLoader試圖尋找這樣的二進位代表。如果這個進程失敗,則拋出一個異常。類被裝載後同時在main方法被調用之前,必須對類 HelloApp與其它類型進行連結然後初始化。以上程式中,靜態域為x,靜態代碼塊部分也是給x賦值,初始化完成後,x的值為30。

下一節重點介紹一下JVM中的Runtime Data Area這一地區。

(新浪微博:@全亮_機器學習)

 

相關文章

聯繫我們

該頁面正文內容均來源於網絡整理,並不代表阿里雲官方的觀點,該頁面所提到的產品和服務也與阿里云無關,如果該頁面內容對您造成了困擾,歡迎寫郵件給我們,收到郵件我們將在5個工作日內處理。

如果您發現本社區中有涉嫌抄襲的內容,歡迎發送郵件至: info-contact@alibabacloud.com 進行舉報並提供相關證據,工作人員會在 5 個工作天內聯絡您,一經查實,本站將立刻刪除涉嫌侵權內容。

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.