對於任何一門語言,要想達到精通的水平,研究它的執行原理(或者叫底層機制)不失為一種良好的方式。在本篇文章中,將重點研究java原始碼的執行原理,即從程
序員編寫JAVA原始碼,到最終形成產品,在整個過程中,都經歷了什麼?每一步又是怎麼執行的?執行原理又是什麼?.....
當然,本篇文章的粒度可能稍微側重於巨集觀方面,更細粒度的技術分析,需要在接下來的該系列文章中與大家分享....
一 編寫java源程式
java原始檔:指儲存java原始碼的檔案;
當前比較主流的JAVA IDE?(1)Intellij IDEA(首推薦)(2)Eclipse
先來看看如下程式碼:
//MyTest被public修飾,故儲存該java原始碼的檔名為MyTest
public class MyTest {
public static void main(String[] args){
System.out.println("Test Java execute process.");
}
}
//由於MyTest被public修飾了,故Class A不能用public修飾
class A{}
//由於MyTest被public修飾了,故Class B不能用public修飾
class B{}
複製程式碼
(1)java原始檔名就是該原始檔中public類的名稱
(2)一個java原始檔可以包含多個類,但只允許一個類為public
二 編譯java原始碼
當java源程式編碼結束後,就需要編譯器編譯,安裝好jdk後,我們開啟jdk目錄,有兩個.exe檔案,
即javac.exe(編譯原始碼,即.java檔案)和java.exe(執行位元組碼,即.class檔案)
1.切換到MyTest.java資料夾
2.javac.exe編譯MyTest.java
編譯後,發現e:\Blogs 目錄多了以class為字尾的檔案:A.class,B.class和MyTest.class
Tip:當javac.exe編譯java原始碼時,java原始碼有幾個類,就會編譯成一個對應的位元組碼檔案(.class檔案),
其中,位元組碼檔案的檔名就是每個類的類名。需要注意的是,類即使不在原始檔中定義,但被原始檔引用,
編譯後,也會程式設計相應的位元組碼檔案,如類A引用類C,但類C不定義在類A的原始檔中,編譯後,類C也被編
譯成對應的位元組碼檔案C.class
三 執行java原始檔
執行java原始檔,用java.exe執行即可
到現在,java源程式基本執行結果,並正確列印我們期望的結果,那麼,如上的步驟,我們可以總結如下:
如上總結,已經抽象化了在JVM中的執行,接下來,我們將分析,位元組碼檔案(.calss檔案)如何在虛擬機器中一步一執行的。
四 JVM如何執行位元組碼檔案
(一) 裝載位元組碼檔案
當.java原始碼被javac.exe編譯器編譯成.class位元組碼檔案後,接下來的工作就交給JVM處理,JVM首先通過類載入器(ClassLoader)
將class檔案和相關Java API載入裝入JVM,以供JVM後續處理。
在該階段中,涉及到如下一些基本概念和知識。
1.JDK,JRE和JVM關係
(1)JDK(Java Development Kit),Java開發工具包,主要用於開發,在JDK7前,JDK包括JRE
(2)JRE(Java Runtime Environment),Java程式執行的核心環境,包括JVM和一些核心庫
(3)JVM(Java Virtual Machine),VM是一種用於計算裝置的規範,它是一個虛構出來的計算機,是通過在實際的計算機上模擬模擬
各種計算機功能來實現的,是JRE核心模組。
2.JVM
JVM是一種用於計算裝置的規範,它是一個虛構出來的計算機,是通過在實際的計算機上模擬模擬各種計算機功能來實現的。Java虛擬機器
虛擬機器的主要任務是裝載class檔案並執行其中的位元組碼,不同的Java虛擬機器中,執行引擎可能由不同的實現,大致有如下幾種引擎:
- 一次性解釋位元組碼引擎
- 即時編譯引擎
- 自適應優化器
關於虛擬機器的實現方式,採用軟體方式、硬體方式和軟體硬體結合方式,這個要根據具體廠商而定。
3.什麼是ClassLoader
虛擬機器的主要任務是裝載class檔案並執行其中的位元組碼,而class檔案是由虛擬機器的類載入器(ClassLoader)完成的,在一個Java虛擬機器,
有可能存在多個類載入器。
任何java運用程式,可能會使用兩種類載入器,即啟動類載入器(bootstrap)和使用者自定義類載入器。
啟動類載入器是Java虛擬機器唯一實現的一部分,它又可分為原始類裝載器,系統類裝載器或預設類裝載器,它的主要作用是從作業系統的
磁碟裝載相應的類,如Java API類等。
使用者自定義裝載類,按照使用者自定義的方式來裝載類。
(二)將位元組碼檔案儲存在JVM記憶體區
當JAVA虛擬機器執行一個程式時,它需要記憶體來儲存許多東西,如位元組碼,從已裝載的class檔案中得到的其他資訊,程式建立的物件,傳遞給
方法的引數,返回值,區域性變數以及運算的中間結果等,這些相關資訊被組織到“執行時資料區”。
根據廠商的不同,在Java虛擬機器中,執行時資料區也有所不同,有些執行時資料區由執行緒共享,有些只能由某個特定執行緒共享。執行時資料區
大致可分幾個區:方法區,堆區,棧區,PC暫存器區和本地方法棧區。
在該階段中,涉及到如下基本概念和知識。
1.方法區
方法區用來儲存解析被載入的class檔案的相關資訊。當虛擬裝載一個class檔案後,它會從這個class檔案包含的二進位制資料中解析型別資訊,然後將
該相關資訊儲存到方法區中。
2.堆
堆是用來儲存相關引用型別的,如new物件。當程式執行時,虛擬機器會把所有該程式在執行時建立的物件都放到堆中。
3.PC暫存器
PC暫存器主要用來儲存執行緒。當新建立一個執行緒時,該執行緒都將得到一個自己的PC暫存器(程式計數器)以及一個java棧。
Java虛擬機器沒有暫存器,其指令集使用Java棧來儲存中間資料。
4.棧區
棧區主要用來儲存值型別的,如基本資料型別,需要注意的時,String為引用型別,是存在堆中的。Java棧是由許多棧
幀組成的,一個棧幀包含一個Java方法呼叫的狀態,當執行緒呼叫一個方法時,虛擬機器壓入一個新的棧幀到該執行緒的Java棧中
,當該方法返回時,這個棧幀從Java棧中彈出。
(三)執行引擎與執行時資料區互動
執行時資料區為執行引擎提供了執行環境和相關資料,執行引擎通過與執行時資料區互動,從而獲取
執行時需要的相關資訊,儲存執行的中間結果等
(四)執行引擎與本地方法介面
當要執行本地方法時,執行引擎將呼叫本地方法介面來獲取相關OS本地方法,需要注意的是,本地方法與作業系統強耦合的。
(五)JVM在具體作業系統上執行
JVM通過呼叫本地介面來獲取本地方法,從而實現在具體的平臺上執行,如在Linux系統上執行,在Window系統上
執行和在Unix系統上執行。
歡迎工作一到五年的Java工程師朋友們加入Java程式設計師開發: 854393687
群內提供免費的Java架構學習資料(裡面有高可用、高併發、高效能及分散式、Jvm效能調優、Spring原始碼,MyBatis,Netty,Redis,Kafka,Mysql,Zookeeper,Tomcat,Docker,Dubbo,Nginx等多個知識點的架構資料)合理利用自己每一分每一秒的時間來學習提升自己,不要再用"沒有時間“來掩飾自己思想上的懶惰!趁年輕,使勁拼,給未來的自己一個交代!