JVM英文全稱為Java Virtual Machine,中文意為Java虛擬機器器。JVM是一種能夠執行Java語言編寫的程式的虛擬機器器器,它首次作為Java語言的一部分,後來又被移植到了許多平臺上。
JVM可以執行Java位元組碼,即Java原始碼經過編譯後生成的二進位制中間程式碼。JVM根據位元組碼指令來執行程式,這就使得Java程式跨平臺,在不同的作業系統上執行時不需要修改原始碼。JVM本身也是跨平臺的,因為JVM實際上就是使用底層機器程式碼實現的軟體層,因此只需安裝相應平臺的JVM即可。
JVM的主要元件包括:
類載入器:負責將.class二進位制檔案轉換為在執行時可以被JVM識別的類物件。
執行時資料區:包括方法區、虛擬機器器棧、本地方法棧、堆等。Java程式在執行時需要佔用這些區域中的記憶體。
執行引擎:負責執行位元組碼指令。
本地方法介面:使得Java程式可以呼叫本地方法,也就是使用C或C++重新編寫的底層程式。
JVM為Java語言提供了許多高階特性,這些特性包括垃圾回收、例外處理、執行緒控制和動態程式碼載入。因此,JVM是許多Java開發者不可缺少的工具,也是Java語言的核心元件之一。
JVM(Java Virtual Machine)是Java程式的執行環境,負責將Java程式碼轉換為機器可以執行的程式碼。JVM執行Java程式的過程如下:
讀取並解析位元組碼檔案:JVM讀取.class檔案並將其解析為JVM可以理解的指令集。這些指令被儲存在方法區(Method Area)中。
載入類:JVM根據程式需要動態地載入類。當需要使用某個類時,JVM會檢查該類是否已經載入過,如果沒有則JVM會從檔案系統或網路中載入該類。
程式計數器指向當前指令:JVM中的程式計數器(Program Counter)指向當前正在執行的指令。在執行指令之前,程式計數器先指向該指令的地址。
執行指令集:JVM通過直譯器或即時編譯器來執行指令集。直譯器逐條解釋指令並執行,而即時編譯器將整段指令編譯成原生程式碼後再執行。執行指令集時,JVM還需要進行記憶體分配、垃圾回收等操作。
程式計數器指向下一條指令:執行完一條指令後,程式計數器會指向下一條指令的地址。這個過程不斷迴圈,直到程式結束或異常丟擲。
總之,JVM負責將Java程式轉換成機器可以執行的程式碼,並提供執行時環境。JVM的執行過程中,會載入類、解釋和執行指令集、記憶體分配和垃圾回收等操作。
JIT(Just-In-Time)編譯器是一種動態編譯器,它在程式執行時將位元組碼翻譯為本地機器程式碼。在JIT編譯器中,程式碼被逐行直譯器執行,當某些程式碼被頻繁呼叫時,JIT編譯器將這些程式碼編譯成本地機器程式碼以提高執行效率。這種編譯方式可以使程式在第一次執行時速度較慢,但在後續執行時速度會顯著提高。JIT編譯器常用於Java虛擬機器器等動態語言環境中。
JVM的記憶體模型是基於Java程式執行時記憶體的管理結構,主要分為以下幾個部分:
程式計數器:每個執行緒都有一個程式計數器,用於記錄當前執行緒執行的位元組碼行號。
虛擬機器器棧:每個執行緒都有一個虛擬機器器棧,用於儲存方法執行時的區域性變數表、運算元棧、動態連線和方法返回值等資訊。
堆:JVM執行時動態分配的記憶體區域,用於儲存Java物件和陣列。
方法區:用於儲存類資訊、常數、靜態變數、即時編譯器編譯後的程式碼等資料。
本地方法棧:與虛擬機器器棧類似,用於儲存本地方法的資訊。
在JVM中,堆是唯一一個被所有執行緒共用的記憶體區域,而每個執行緒都有自己的程式計數器、虛擬機器器棧和本地方法棧。同時,方法區也是被所有執行緒所共用的。JVM的記憶體模型為Java程式提供了良好的記憶體管理機制,能夠有效地提高程式的效能和安全性。
JVM中的垃圾回收器是一種自動記憶體管理機制,它負責回收在程式中不再被使用的物件,並將這些記憶體釋放回給作業系統。垃圾回收器通過掃描參照關係來確定哪些記憶體是「垃圾」,並將其標記為可回收。它可以大大減少程式設計師手動釋放記憶體的工作量,提高程式的安全性和可靠性,但也會在一定程度上影響程式的效能。JVM中有很多不同型別的垃圾回收器,例如標記清除垃圾回收器、複製垃圾回收器、標記整理垃圾回收器等。這些垃圾回收器有不同的實現方式和適用場景,程式設計師需要根據需求選擇合適的垃圾回收器。
下面是一個使用Java語言的程式碼範例,演示垃圾回收器如何回收無用物件。
public class GarbageCollectionExample {
public static void main(String[] args) {
// 建立一個物件
Person p = new Person();
// 將物件設定為null,表示不再參照該物件
p = null;
// 垃圾回收器會在這裡回收無用物件
}
}
class Person {
// 將在這裡新增Person類的屬性和方法
}
在上述範例中,建立了一個名為Person的類,並範例化了一個物件p。然後將p設定為null,表示不再參照該物件。當垃圾回收器檢測到該物件沒有任何參照變數參照時,就會回收該物件並釋放其佔用的記憶體。
JVM中的四種參照型別:
public class ReferenceExample {
public static void main(String[] args) {
// 強參照
Object strongRef = new Object();
// 軟參照
SoftReference<Object> softRef = new SoftReference<>(new Object());
// 弱參照
WeakReference<Object> weakRef = new WeakReference<>(new Object());
// 虛參照
ReferenceQueue<Object> refQueue = new ReferenceQueue<>();
PhantomReference<Object> phanRef = new PhantomReference<>(new Object(), refQueue);
// 嘗試回收
System.gc();
// 判斷是否回收成功
System.out.println(strongRef);
System.out.println(softRef.get());
System.out.println(weakRef.get());
System.out.println(phanRef.get());
}
}
JVM載入和查詢類檔案的過程如下:
1.類載入器的工作:JVM負責從檔案系統、JAR包或網路中載入類檔案,並交給類載入器去載入。類載入器通常有四種:
2.類檔案的查詢:類載入器會按照類的完全限定性類名(Fully Qualified Class Name,FQCN)去查詢類檔案。類的FQCN即包名+類名。
3.類檔案的載入:當類載入器找到並讀取了類檔案後,JVM會根據類檔案的結構建立一個表示該類的Class物件,並將其存放在JVM內部的方法區中,即類的後設資料區。這個Class物件包含了該類的所有資訊,如類名、類的修飾符、欄位、方法等。
4.類的初始化:當類檔案被載入後,JVM並不立即執行靜態程式碼塊和靜態變數的預設初始化賦值,而是等待需要被初始化類的首次主動使用時才執行。
5.類的連結:為了使類能夠正確執行,JVM需要對類進行連結。連結分為三個階段:
6.類的使用:當一個類被載入、連結和初始化後,就可以被使用了。類的使用包括建立物件、呼叫方法、存取靜態變數、執行靜態程式碼塊等。
JVM的效能調優需要注意以下幾個點:
堆記憶體設定:JVM的堆大小設定對系統的效能影響很大,應該根據實際情況進行適當的調整。
垃圾回收設定:垃圾回收機制對系統的效能影響也非常大,應該根據應用的負載情況和記憶體使用情況進行適當的調整。
執行緒池設定:執行緒池的大小設定影響系統的並行能力和效能,應根據實際情況進行適當調整。
JVM引數設定:JVM提供了很多設定引數,如記憶體分配、GC演演算法和堆大小等,應根據實際情況進行適當調整。
應用程式碼優化:應用的程式碼質量和設計對系統的效能也有影響,應該進行優化以提高系統的效能。
系統資源設定:系統的硬體資源設定也對系統的效能有較大的影響,應根據實際情況進行適當的調整。
可以通過以下幾種方式來監控JVM的執行狀態:
JVisualVM:JVisualVM是一個監控和分析JVM的工具,可以檢視記憶體使用、執行緒狀態、GC情況、類載入等資訊。需要在JDK的bin目錄下執行jvisualvm命令啟動。
jstat:jstat是JVM自帶的監控工具,可以檢視JVM的堆、非堆記憶體使用情況、GC情況等。通過命令列方式執行。
JMX:JMX是Java Management Extension的簡稱,可以通過JMX介面來監控和管理Java應用程式。可以使用JConsole等工具檢視JVM的執行狀況。
第三方工具:如AppDynamics、New Relic等都是常用的監控工具,可以通過整合agent來監控JVM的執行狀態。
JVM(Java虛擬機器器)可以保證Java程式的安全性,主要體現在以下幾個方面:
類載入機制:JVM在程式執行時會將需要的類載入到記憶體中,並進行校驗、解析和初始化,確保類的可靠性和正確性。如果類有被篡改或不正確的地方,JVM在載入時會直接丟擲異常,防止不安全的程式碼被執行。
記憶體管理:JVM會提供記憶體分配、回收和存取保護等功能,防止程式出現記憶體洩露或越界存取等安全問題。
安全管理器:JVM可以通過安全管理器(Security Manager)實現對Java程式進行存取控制,限制程式對系統資源的存取,防止惡意程式碼執行或對系統造成危害。
位元組碼校驗:在將Java程式碼編譯成位元組碼之前,編譯器會對程式碼進行各種檢查,檢驗其是否符合Java語言規範和安全要求。JVM在執行位元組碼時會再次對其進行驗證,確保程式碼的安全性。
安全沙箱:JVM還提供了安全沙箱(Security Sandbox)機制,將Java程式執行在一個獨立的安全環境中,能夠限制其對檔案系統、網路等系統資源的存取,從而防止惡意程式碼對系統的攻擊。