java一直宣傳的口號是:一次編譯,處處運行。那麼它如何實現的呢?咱們看下圖:java
java程序通過一次編譯以後,將java代碼編譯爲字節碼也就是class
文件,而後在不一樣的操做系統上依靠不一樣的java虛擬機
進行解釋,最後再轉換爲不一樣平臺的機器碼,最終獲得執行。這樣咱們是否是能夠推演,若是要在mac系統上運行,是否是隻須要安裝mac java虛擬機
就好了。那麼瞭解了這個基本原理後,咱們來看一下,一段程序是如何執行的。linux
public class HelloWorld { public static void main(String[] args) { System.out.print("Hello world"); } }
這段程序從編譯到運行,所經歷的過程以下:windows
可能經過上面的描述,你們對JVM運行流程有了一個粗略的認識,那麼JVM內部究竟是怎麼執行一個class文件的呢?jvm
JVM內存空間包含:方法區、java堆、java棧、本地方法棧。函數
方法區是各個線程共享
的區域,存放類信息、常量、靜態變量。操作系統
java堆也是線程共享
的區域,咱們的類的實例就放在這個區域,能夠想象你的一個系統會產生不少實例,所以java堆的空間也是最大的。若是java堆空間不足了,程序會拋出OutOfMemoryError異常。線程
java棧是每一個線程私有
的區域,它的生命週期與線程相同,一個線程對應一個java棧,每執行一個方法
就會往棧中壓入一個元素,這個元素叫「棧幀」,而棧幀
中包括了方法中的局部變量、用於存放中間狀態值的操做棧,若是java棧空間不足了,程序會拋出StackOverflowError異常.code
每一個幀表明一個方法,Java方法有兩種返回方式,return和拋出異常,兩種方式都會致使該方法對應的幀出棧和釋放內存。對象
本地方法棧角色和java棧相似,只不過它是用來表示執行本地方法的,本地方法棧存放的方法調用本地方法接口,最終調用本地方法庫,實現與操做系統、硬件交互的目的。接口
PC寄存器(程序計數器),說到這裏咱們的類已經加載了,實例對象、方法、靜態變量都去了本身改去的地方,那麼問題來了,程序該怎麼執行,哪一個方法先執行,哪一個方法後執行,這些指令執行的順序就是PC寄存器在管,它的做用就是控制程序指令的執行順序。
執行引擎固然就是根據PC寄存器調配的指令順序,依次執行程序指令。
- 靜態變量+常量+類信息+運行時常量池存在方法區中,實例變量存在堆內存中。
- 基本類型的變量和對象的引用變量都是在函數的棧內存中分