jvm原理和代碼運行的過程

一次編譯,處處運行

java一直宣傳的口號是:一次編譯,處處運行。那麼它如何實現的呢?咱們看下圖:java

graph TD java原程序--javac編譯-->java字節碼 java字節碼-->jvm虛擬機 jvm虛擬機--java解釋-->windows機器碼 jvm虛擬機--java解釋-->linux機器碼 windows機器碼-->windows執行 linux機器碼-->linux執行

java程序通過一次編譯以後,將java代碼編譯爲字節碼也就是class文件,而後在不一樣的操做系統上依靠不一樣的java虛擬機進行解釋,最後再轉換爲不一樣平臺的機器碼,最終獲得執行。這樣咱們是否是能夠推演,若是要在mac系統上運行,是否是隻須要安裝mac java虛擬機就好了。那麼瞭解了這個基本原理後,咱們來看一下,一段程序是如何執行的。linux

public class HelloWorld {
    public static void main(String[] args) {        
        System.out.print("Hello world"); 
    }
}

這段程序從編譯到運行,所經歷的過程以下:windows

graph TD java源代碼--class文件-->java字節碼 java字節碼--加載jvm.cfg文件-->加載配置 加載配置--根據jvm.cfg的配置-->加載jvm.dll文件 加載jvm.dll文件-->初始化jvm 初始化jvm-->獲取JNI接口 獲取JNI接口--JNI爲本地方法他能夠直接與操做系統交互-->操做Class文件 操做Class文件-->找到main文件執行

jvm基本結構

可能經過上面的描述,你們對JVM運行流程有了一個粗略的認識,那麼JVM內部究竟是怎麼執行一個class文件的呢?jvm

graph TD Class文件-->類加載器 類加載器-->內存空間 內存空間--運行時常量池-->方法區 方法區-->垃圾回收GC 內存空間--對象存儲-->java堆 java堆-->垃圾回收GC 內存空間--局部變量表_棧幀_操做數-->java棧 java棧--線程結束自動釋放-->線程私有 內存空間--本地方法庫_C語言-->本地方法棧 本地方法棧-->線程私有 內存空間--JNI直接操做-->堆外內存

jvm內存分類介紹

JVM內存空間包含:方法區、java堆、java棧、本地方法棧。函數

  1. 方法區是各個線程共享的區域,存放類信息、常量、靜態變量。操作系統

  2. java堆也是線程共享的區域,咱們的類的實例就放在這個區域,能夠想象你的一個系統會產生不少實例,所以java堆的空間也是最大的。若是java堆空間不足了,程序會拋出OutOfMemoryError異常。線程

  3. java棧是每一個線程私有的區域,它的生命週期與線程相同,一個線程對應一個java棧,每執行一個方法就會往棧中壓入一個元素,這個元素叫「棧幀」,而棧幀中包括了方法中的局部變量、用於存放中間狀態值的操做棧,若是java棧空間不足了,程序會拋出StackOverflowError異常.code

每一個幀表明一個方法,Java方法有兩種返回方式,return和拋出異常,兩種方式都會致使該方法對應的幀出棧和釋放內存。對象

  1. 本地方法棧角色和java棧相似,只不過它是用來表示執行本地方法的,本地方法棧存放的方法調用本地方法接口,最終調用本地方法庫,實現與操做系統、硬件交互的目的。接口

  2. PC寄存器(程序計數器),說到這裏咱們的類已經加載了,實例對象、方法、靜態變量都去了本身改去的地方,那麼問題來了,程序該怎麼執行,哪一個方法先執行,哪一個方法後執行,這些指令執行的順序就是PC寄存器在管,它的做用就是控制程序指令的執行順序。

執行引擎固然就是根據PC寄存器調配的指令順序,依次執行程序指令。

  • 靜態變量+常量+類信息+運行時常量池存在方法區中,實例變量存在堆內存中。
  • 基本類型的變量和對象的引用變量都是在函數的棧內存中分
相關文章
相關標籤/搜索