溫馨提示×

溫馨提示×

您好,登錄后才能下訂單哦!

密碼登錄×
登錄注冊×
其他方式登錄
點擊 登錄注冊 即表示同意《億速云用戶服務條款》

Java程序是如何執行的

發布時間:2020-12-14 14:47:35 來源:億速云 閱讀:352 作者:Leah 欄目:開發技術

這篇文章將為大家詳細講解有關Java程序是如何執行的,文章內容質量較高,因此小編分享給大家做個參考,希望大家閱讀完這篇文章后對相關知識有一定的了解。

Java程序執行過程

Java程序是如何執行的

  • 步驟 1: 寫源代碼,源代碼將以.java的文件格式保存在電腦硬盤中。

  • 步驟 2: 編譯器(compiler)檢查是否存在編譯期錯誤(例如缺少分號,關鍵字拼寫錯誤等)。若通過檢測,編譯器就會將源代碼翻譯成字節碼(bytecode),以.class的文件格式保存在電腦硬盤中。

  • 步驟 3: 若要運行此Java程序,JVM中會有一個叫類加載器(class loader)的內置程序把字節碼從硬盤載入到正位于內存中的JVM里去。

  • 步驟 4: JVM中還有一個叫字節碼校驗器(bytecode verifier)的內置程序檢測是否存在運行期錯誤(例如棧溢出)。若通過檢測,字節碼校驗器就會將字節碼傳遞給解釋器(interpreter)。

  • 步驟 5: 解釋器會對字節碼進行逐行翻譯,將其翻譯成當前所在系統可以理解的機器碼(machine code),

  • 步驟 6:將機器碼交給操作系統,操作系統會以main方法作為入口開始執行程序。至此,一個Java程序就這樣運行起來了。

細心的讀者可能注意到了,在流程圖中還涉及到一個叫JIT的東西在步驟中沒有被解釋。那么JIT編譯器(Just-In-Time Compiler)是如果參與進程序的執行過程中呢?讓我們來看以下兩個例子。

Java程序是如何執行的

  • 情況 1: 解釋器對代碼進行逐行解釋,正如我們在步驟中所介紹的。

  • 情況 2: 這是JIT編譯器參與進Java執行過程的情況,JIT編譯器會掃描所有代碼并對其進行優化。例如此時它發現最后一行代碼是重復多余的,就會將其移除,只傳遞前4行代碼給解釋器。這樣解釋器就能運行地更快速高效,畢竟少了一行多余的代碼需要翻譯。

當然,這只是JIT編譯器的優化手段之一,不同公司設計的JIT編譯器對Java程序的運行會有不同的優化方式。此外需要知道的是,JIT編譯器并不是每次都會參與到執行過程中來。

內存機制

在步驟3中我們談到字節碼會被類加載器載入到內存,那么載入之后JVM是如何對其進行內存管理的呢?

通常,在載入內存后,一個Java程序所占用的內存會被大致分為3塊區域:堆(heap),棧(stack)和方法區(method area)。

Java程序是如何執行的

堆:存放new出來的東西。

棧:存放局部變量。

方法區:類型信息,字段信息,常量池(constant pool),靜態變量,方法信息等。

public final class Student extends Object implements Serializable
{ 
// 1.類信息 
// 2.對象字段信息 
private String name; 
private int score; 
// 3.常量池 
public final int id = 0; 
public final String gender = "male"; 
// 4.靜態變量 
public static int a = 0; 
// 5.方法信息 
public int getid() 
{ 
return id; 
}}

PC寄存器:存放將要執行的指令的地址。(因為機器的腦子不靈活,所以需要一塊專門的區域幫他記住執行到哪一步,不然它會忘記)

本地方法棧:與JVM棧所發揮的作用是非常相似的,其區別不過是JVM棧為Java方法服務,而本地方法棧則是為使用到的Native方法服務。有的虛擬機(例如Sun HotSpot虛擬機)甚至直接就把本地方法棧和虛擬機棧合二為一。

每個線程擁有各自獨立的(虛擬機)棧、PC寄存器和本地方法棧。而堆和方法區則是所有線程共享的。

最后讓我們通過一個小例子來理解Java程序執行時內存的變化。

public class Person 
{
int id; int age; Person(int id1, int age1)
{ 
id = id1; age = age1; 
} 
public static void main(String[] args) 
{ 
Person Tom = new Person(1, 25); 
} 
}

首先,在stack中申請了一塊內存,這塊內存區域名字叫Tom,此時區域里存儲的內容為null。

接著,調用Person的構造方法,方法的參數屬于局部變量,因此在stack中有兩塊區域分別存放id1和age1。

通過構造方法,可以new出來一個Person的對象,這個對象連帶著其成員變量會被存放在heap中。成員變量id和age的值由存放在stack中的局部變量id1和age1賦予。

最后,將這個對象的引用值(類似于地址)傳遞給Tom,通過引用值我們就可以找到這個對象。

Java程序是如何執行的

(注意:位于stack中的id1和age1會隨著構造方法調用的結束而消失,這里為了更好地表現全過程,因此保留在圖中。)

關于棧和堆的其他小知識

  • 棧和堆的大小都是固定為一個默認值的,它們作為jvm的參數設定好了,不同的jvm設定的參數不同,相應的棧和堆的大小也就不同。

  • 棧是運行時的單位:里面存儲的信息都是跟當前線程相關的,包括局部變量、程序運行狀態、方法返回值等;而堆是存儲的單位:它只負責存儲對象。

  • 當一個方法調用結束后,方法里的局部變量會隨之消失,不會在stack中繼續占用空間。棧與堆的分離使得不同線程可以訪問同一個對象,這是一種有效的數據交互方式(共享內存);此外也節省了空間,因為堆中的共享常量和緩存可以被所有棧訪問。

關于Java程序是如何執行的就分享到這里了,希望以上內容可以對大家有一定的幫助,可以學到更多知識。如果覺得文章不錯,可以把它分享出去讓更多的人看到。

向AI問一下細節

免責聲明:本站發布的內容(圖片、視頻和文字)以原創、轉載和分享為主,文章觀點不代表本網站立場,如果涉及侵權請聯系站長郵箱:is@yisu.com進行舉報,并提供相關證據,一經查實,將立刻刪除涉嫌侵權內容。

AI

亚洲午夜精品一区二区_中文无码日韩欧免_久久香蕉精品视频_欧美主播一区二区三区美女