Java程序編譯和運行的過程

          Java整個編譯以及運行的過程至關繁瑣,本文經過一個簡單的程序來簡單的說明整個流程。       java

          以下圖,Java程序從源文件建立到程序運行要通過兩大步驟:一、源文件由編譯器編譯成字節碼(ByteCode)  二、字節碼由java虛擬機解釋運行。由於java程序既要編譯同時也要通過JVM的解釋運行,因此說Java被稱爲半解釋語言( "semi-interpreted" language)。jvm


圖1   java程序編譯運行過程函數

 

        下面經過如下這個java程序,來講明java程序從編譯到最後運行的整個流程。代碼以下:this

 

Java代碼   收藏代碼
  1. //MainApp.java  
  2. public class MainApp {  
  3.     public static void main(String[] args) {  
  4.         Animal animal = new Animal("Puppy");  
  5.         animal.printName();  
  6.     }  
  7. }  
  8. //Animal.java  
  9. public class Animal {  
  10.     public String name;  
  11.     public Animal(String name) {  
  12.         this.name = name;  
  13.     }  
  14.     public void printName() {  
  15.         System.out.println("Animal ["+name+"]");  
  16.     }  
  17. }  

 

        第一步(編譯): 建立完源文件以後,程序會先被編譯爲.class文件。Java編譯一個類時,若是這個類所依賴的類尚未被編譯,編譯器就會先編譯這個被依賴的類,而後引用,不然直接引用,這個有點象make。若是java編譯器在指定目錄下找不到該類所其依賴的類的.class文件或者.java源文件的話,編譯器話報「cant find symbol」的錯誤。spa

        編譯後的字節碼文件格式主要分爲兩部分: 常量池方法字節碼。常量池記錄的是代碼出現過的全部token(類名,成員變量名等等)以及符號引用(方法引用,成員變量引用等等);方法字節碼放的是類中各個方法的字節碼。下面是MainApp.class經過反彙編的結果,咱們能夠清楚看到.class文件的結構:
圖2  MainApp類常量池  
 

圖3  MainApp類方法字節碼
           第二步(運行):java類運行的過程大概可分爲兩個過程:一、類的加載  二、類的執行。須要說明的是:JVM主要在程序第一次主動使用類的時候,纔會去加載該類。也就是說,JVM並非在一開始就把一個程序就全部的類都加載到內存中,而是到不得不用的時候才把它加載進來,並且只加載一次。
        下面是程序運行的詳細步驟:
  1. 在編譯好java程序獲得MainApp.class文件後,在命令行上敲java AppMain。系統就會啓動一個jvm進程,jvm進程從classpath路徑中找到一個名爲AppMain.class的二進制文件,將MainApp的類信息加載到運行時數據區的方法區內,這個過程叫作MainApp類的加載。
  2. 而後JVM找到AppMain的主函數入口,開始執行main函數。
  3. main函數的第一條命令是Animal  animal = new Animal("Puppy");就是讓JVM建立一個Animal對象,可是這時候方法區中沒有Animal類的信息,因此JVM立刻加載Animal類,把Animal類的類型信息放到方法區中。
  4. 加載完Animal類以後,Java虛擬機作的第一件事情就是在堆區中爲一個新的Animal實例分配內存, 而後調用構造函數初始化Animal實例,這個Animal實例持有着指向方法區的Animal類的類型信息(其中包含有方法表,java動態綁定的底層實現)的引用。
  5. 當使用animal.printName()的時候,JVM根據animal引用找到Animal對象,而後根據Animal對象持有的引用定位到方法區中Animal類的類型信息的方法表,得到printName()函數的字節碼的地址。
  6. 開始運行printName()函數。

 圖4   java程序運行過程
特別說明:java類中全部public和protected的實例方法都採用動態綁定機制,全部私有方法、靜態方法、構造器及初始化方法<clinit>都是採用靜態綁定機制。而使用動態綁定機制的時候會用到方法表,靜態綁定時並不會用到。本文只是講述java程序運行的大概過程,因此並無細加區分。本文的所述的流程很是粗糙,想深刻了解的讀者請查閱其餘資料。存在謬誤的地方,請多指正。
相關文章
相關標籤/搜索