1. 程式人生 > >java虛擬機器執行機制

java虛擬機器執行機制

    首先簡單闡述下解釋型語言和編譯型語言的聯絡與區別。

    編譯型語言是通過編譯器將程式編譯成目標機器所能識別的機器碼,而解釋型語言不需要編譯過程。由該語言的直譯器讀取指令碼,按照語法規則進行解釋,然後呼叫直譯器內建的命令(或者庫函式)。例如,C語言的printf()函式經過靜態編譯後,printf()所需的所以程式碼都以機器碼的形式寫入可執行檔案中,shell在執行程式時,在指定路徑搜尋該檔案,然後載入器(Loader)載入該程式的ELF檔案到記憶體中,跳轉到程式入口,將控制權交由該程式。動態編譯的情況有些不同。由於printf()是很常用的函式,系統將常用函式集中起來做成庫,當我寫一個Myprintf()函式時呼叫printf() 時,動態編譯後形成的ELF檔案不會包含printf()相關的程式碼,但是會有些資訊告訴系統:“我的程式將會呼叫printf(),因此我需要printf()的地址”。載入ELF檔案後,首先執行動態聯結器(ldd),ldd知道程式依賴的動態庫,系統中如果沒有載入該動態庫,就會通知系統載入該庫,並把庫函式的入口地址繫結到程式需要的地方,然後跳轉到程式入口地址,開始執行程式。

這裡,我們所寫的程式一經編譯,就變成特定機器的機器碼和一些附屬資訊(符號表,地址,變數值等),然後通過系統載入執行機制就變成“動態程式”——程序。

    解釋型語言的執行過程離不開直譯器,python,perl,ruby等等。所以指令碼的第一行一般是#/usr/bin/×××。×××代表了各語言相應的直譯器。指令碼一般由表示式(expression)和Block of expressions組成,直譯器首先要做的就是分析並理解表示式結構,形成“執行序列”。這個“執行序列”是中立的,不針對任何native machine(呵呵,我起的名字,相對於viutural machine。),所以“可移植性”高。這裡不用“位元組碼”代替“執行序列”是考慮到在jvm中有位元組碼的概念,他們之間有顯著的不同。決定執行序列是直譯器最主要的作用。假設,python輸出的函式為python_print(),那麼python直譯器在“解釋”指令碼時遇到這個表示式就將呼叫系統的print()函式執行輸出操作。你也可以把指令碼理解成高階配置檔案,這個檔案指導python直譯器如何執行,直譯器內部已經制訂了“如何”執行的若干規則。

    JVM執行java程式要比上述兩個複雜,因為它已經被稱作machine了。下圖是JVM的結構框圖。主要包含:垃圾回收器,類載入子系統,執行引擎,執行時資料區等。


如果能較詳細的理解這幅圖,那麼JVM的執行機制就大體過關了。下面試著分析上述各模組的功能和它們之間的相互聯絡。

類載入過程

java程式經過編譯後形成*.class檔案,內含JVM的位元組碼。通過類載入器將位元組碼(*.class)載入入JVM的記憶體中。類載入過程主要涉及JVM的方法區。方法區儲存了類的型別資訊,如執行時常量池(Runtime Constant Pool)、欄位和方法資料、建構函式和普通方法的位元組碼內容、還包括一些在類、例項、介面初始化時用到的特殊方法

。這些都可以看作靜態資訊,每次方法被呼叫,在java棧中保持該方法的臨時變數,當方法返回時,java棧自動撤消。JVM將類載入過程分成載入,連線,初始化三個階段,其中連線階段又細分為驗證,準備,解析三個階段。

1、Java程式開始執行前,類載入器載入類名.class,將類資訊儲存在執行時資料區的方法區。方法區是執行緒共享的,裡面儲存的資訊有一個共同的特定就是整個程式中是唯一的。所以有關class的版本號,常量池,方法的位元組碼等。而類的非靜態域則是物件相關的,儲存在堆區,其引用(類似指標)存放在棧區。下面的例子,編譯後產生AppMain.class,JVM載入AppMain.class後,將位元組碼解析成執行時資料結構。類的靜態變數和方法存放在方法區。JVM主執行緒執行main()函式,new一個Sample的物件。

AppMain.java
public class AppMain //執行時, jvm 把appmain的資訊都放入方法區
{
    public static void main(String[] args)  //main 方法本身放入方法區。
    {
        Sample test1 = new  Sample( " 測試1 " );  //test1是引用,所以放到棧區裡, Sample是自定義物件應該放到堆裡面       
        Sample test2 = new  Sample( " 測試2 " );
        test1.printName();
        test2.printName();
    } 
}

這時就會到方法區尋找Sample的型別資訊,發現還沒有載入,就會載入Sample.class。在堆中分配記憶體並建立一個Sample物件,它的引用是test1。堆中的物件持有class的引用,即指向方法區中類的型別資訊的地址。test1是main()函式的私有變數所以保持在主執行緒棧上,它執行堆中的Sample物件。

Sample.java
public class Sample     //執行時, jvm 把appmain的資訊都放入方法區
{
    private name;      //new Sample例項後,name引用放入棧區裡,name物件放入堆裡
    public Sample(String name)
   {
        this .name = name;
    } 
    public void printName()   //print方法本身放入方法區裡。
    {
        System.out.println(name);
    } 

} 
下圖是執行時的示意圖


連線過程

2、連線過程主要是在載入之後、初始化之前的一些準備工作。他們有很多交叉的地方。連線時需要驗證位元組碼是否符合java規範,資料型別是否有效,繼承和實現是否合乎標準。在這個階段還為類的靜態變數分配空間,並將其設定成JVM的預設值。對於非靜態變數則不會賦值。

在jvm中各型別的初始值如下:

  • int,byte,char,long,float,double 預設初始值為0
  • boolean 為false(在jvm內部用int表示boolean,因此初始值為0)
  • reference型別為null
  • final static基本型別或者String型別,則直接採用常量值(這實際上是在編譯階段就已經處理好了)

這一階段還需要出發解析過程。JVM對於每個載入的類都會有在內部建立一個執行時常量池(參考上面圖示),在解析之前是以字串的方式將符號引用儲存在執行時常量池中,在程式執行過程中當需要使用某個符號引用時,就會促發解析的過程,解析過程就是通過符號引用查詢對應的類實體,然後用直接引用替換符號引用。由於符號引用已經被替換成直接引用,因此後面再次訪問時,無需再次解析,直接返回直接引用。

相關推薦

java虛擬機器執行機制

    首先簡單闡述下解釋型語言和編譯型語言的聯絡與區別。     編譯型語言是通過編譯器將程式編譯成目標機器所能識別的機器碼,而解釋型語言不需要編譯過程。由該語言的直譯器讀取指令碼,按照語法規則進行解釋,然後呼叫直譯器內建的命令(或者庫函式)。例如,C語言的printf(

Java虛擬機器(JVM原始碼):JDK10對Java虛擬機器執行時資料區的劃分(詳細圖解)

Java虛擬機器執行時資料區 為什麼要研究這個,因為JDK都已經發布到10了,必須要更新自己對Java虛擬機器新的認識。 一、執行時資料區的劃分 1.1 官方劃分 關於JDK10對執行時資料區的劃分,在官方文件說的非常清楚。 學習技術,一定要學會看第一手資料。 Ja

java虛擬機器執行時記憶體區域

java虛擬機器執行時記憶體區域 程式計數器、Java虛擬機器棧、本地方法棧、Java堆、方法區 (前3個為執行緒私有,後2個為執行緒共享) (1)程式計數器 當前執行緒所執行的位元組碼的行號指示器;通過改變這個計數器的值來選取下一條需要執行的位元組碼指令;分支、迴圈、跳

JAVA虛擬機器執行時記憶體劃分--執行時資料區域

Java虛擬機器在執行java程式時會把記憶體劃分為以下幾個不同的資料區域: java虛擬機器記憶體劃分(執行時)1、執行緒私有的:   程式計數器(Program Counter Register):可以看作當前執行緒所執行的位元組碼的行號指示器。java多執行緒中一個時刻,一個處理器都只會執行一條執

java虛擬機器執行時資料區

Java在執行Java程式的過程中會把它所管理的記憶體劃分為若干個不同的資料區域。這些區域都有各自的用途、建立和銷燬的時間,有一些是隨虛擬機器的啟動而建立,隨虛擬機器的退出而銷燬,有些則是與執行緒一一對應,隨執行緒的開始和結束而建立和銷燬。 Java虛擬機器所管理的記憶

Java虛擬機器——執行時資料區域

java虛擬機器章執行java程式的過程中會把它所管理的記憶體劃分為若干個不同的資料區域,這些區域都有各自的用途。 1、程式計數器(執行緒私有 程式計數器是一塊較小的 記憶體區域,它可以看做是當前執行緒所執行的位元組碼的行號指示器。位元組碼直譯器工作時就是通過改變這個計數

Java虛擬機器執行時資料區域

對於HotSpot虛擬機器而言,很多人將方法區稱為持久代,本質上兩者並不等價,只是因為HotSpot虛擬機器使用永久代實現方法區而已,但是該方案現在看來並不是很好,這樣的方式更容易導致記憶體溢位。在jdk1.7以後的版本,已經使用Native memory來實現方法區。Java虛擬機器規範對這部分的限制非常寬

JVM虛擬機器執行機制

什麼是JVM? 虛擬機器是物理機器的軟體實現。Java是用在VM上執行的WORA(Write Once Run Anywhere)概念而開發的。編譯器將Java檔案編譯為Java .class檔案,然後將.class檔案輸入到JVM中,JVM會載入並執行類檔案。 JVM基本概

Java虛擬機器-----執行時棧結構

Java 虛擬機器棧       該區域也是執行緒私有的,它的生命週期也與執行緒相同。虛擬機器棧描述的是 Java 方法執行的記憶體模型:每個方法被執行的時候都會同時建立一個棧幀,棧它是用於支援續虛擬機器進行方法呼叫和方法執行的資料結構。對於執行引擎來講,活動

JDK1.8-Java虛擬機器執行時資料區域和HotSpot虛擬機器的記憶體模型

官方文件規定的執行時資料區域 官方文件中規定的執行時資料區一共就幾塊: PC計數器, 虛擬機器棧, 本地方法棧, 堆區,

關於Java虛擬機器執行時資料區域的總結

Java虛擬機器執行時資料區域 程式計數器(Program Counter) 程式計數器作為一個概念模型,這個是用來指示下一條需要執行的位元組碼指令在哪。 Java的多執行緒實際上是通過執行緒輪轉做到的,如果是一個單核的機器(或單cpu),嚴格意義上在一個時間塊中只會有一個執行緒在執行。為了執行緒切換以後能

【JVM從小白學成大佬】2.Java虛擬機器執行時資料區

目錄 1.執行時資料區介紹 2.堆(Heap) 是否可能有兩個物件共用一段記憶體的事故? 3.方法區(Method Area) 4.程式計數器(Program Counter

Java 虛擬機器執行時資料區詳解

> 本文摘自深入理解 Java 虛擬機器第三版 ## 概述 Java 虛擬機器在執行 Java 程式的過程中會把它所管理的記憶體劃分為若干個不同的資料區域,這些區域有各自的用途,以及建立和銷燬的時間,有的區域隨著虛擬機器程序的啟動而一直存在,有的區域則是依賴使用者執行緒的啟動和結束而建立和銷燬。因

深入理解Java虛擬機器(類檔案結構+類載入機制+位元組碼執行引擎)

周志明的《深入理解Java虛擬機器》很好很強大,閱讀起來頗有點費勁,尤其是當你跟隨作者的思路一直探究下去,開始會讓你弄不清方向,難免有些你說的啥子的感覺。但知識不得不學,於是天天看,反覆看,就慢慢的理解了。我其實不想說這種硬磨的方法有多好,我甚至不推薦,我建議大家閱讀這本書時,由淺入深,有舍有得,先從巨集觀去

二、Java虛擬機器自動記憶體管理機制執行時資料區域深入瞭解

執行時資料區域:     (1)、程式計數器         a、定義:是一塊較小的記憶體空間,可以看作是當前執行緒所執行的位元組碼的行號指示器。         b、執行緒私有:因為多執行緒是通過執行緒輪流切換並且分配處理器執行時間的方式來實現的,任何時刻,        

Java程式的執行機制Java虛擬機器

1、java程式的執行Java中原始檔字尾為*.java,編譯(也就是javac命令)使*.java檔案轉換為*.class檔案,然後在計算機上執行(java命令)*.class檔案。這就是java程式的執行過程,那麼JVM(java虛擬機器)是做什麼用的哪?首先我們來看一下

《深入理解Java虛擬機器》個人讀書總結——虛擬機器類載入機制

我們都知道Java虛擬機器是用來執行我們編譯好的.class檔案的,class檔案中夾帶類的各種資訊,虛擬機器要執行這些檔案,第一件事就是要載入到虛擬機器中,這就引出了這次總結的問題——虛擬機器是如何載入這些class檔案的?載入後虛擬機器是怎麼處理檔案中夾帶的資訊的? 類載入機制

關於Class物件、類載入機制虛擬機器執行時記憶體佈局的全面解析和推測

簡介: 本文是對Java的類載入機制,Class物件,反射原理等相關概念的理解、驗證和Java虛擬機器中記憶體佈局的一些推測。本文重點講述瞭如何理解Class物件以及Class物件的作用。 歡迎探討,如有錯誤敬請指正 如需轉載,請註明出處 http://www.cnblogs.com/nul

三、Java虛擬機器自動記憶體管理機制、物件建立及記憶體分配

  1、物件是如何建立: 步驟:    (1)、虛擬機器遇到new <類名>的指令---->根據new的引數是否在常量池中定位一個類的符號引用    (2)、檢測該符號引用代表的類是否已經被載入、解析、和初始化。(如果沒有則

java虛擬機器1.執行時資料區

Java技術體系模組圖 java虛擬機器在執行java程式的過程中會把它所管理的記憶體劃分為若干個不同的資料區域。這些區域都有各自的用途,以及各自的建立和銷燬時間,有的區域隨虛擬機器程序的啟動而存在,有些區域則依賴使用者執行緒的啟動和結束而建立和銷燬。 程式計數器 是一塊較小的記憶體空