面試---關於jvm的組成

JVM(Java 虛擬機)算是面試必問的問題的了。

而但凡問 JVM 一定會問的第一個問題就是:講一講 JVM 的組成?那本文就講一下 JVM 的組成。

首先來說 JVM 的組成分爲,整體組成部分和運行時數據區組成部分。

面試---關於jvm的組成
一、JVM 整體組成
JVM 整體組成可分爲以下四個部分:

類加載器(ClassLoader)
運行時數據區(Runtime Data Area)
執行引擎(Execution Engine)
本地庫接口(Native Interface)
各個組成部分的用途:

程序在執行之前先要把java代碼轉換成字節碼(class文件),jvm首先需要把字節碼通過一定的方式 類加載器(ClassLoader) 把文件加載到內存中 運行時數據區(Runtime Data Area) ,而字節碼文件是jvm的一套指令集規範,並不能直接交個底層操作系統去執行,因此需要特定的命令解析器 執行引擎(Execution Engine) 將字節碼翻譯成底層系統指令再交由CPU去執行,而這個過程中需要調用其他語言的接口 本地庫接口(Native Interface)來實現整個程序的功能,這就是這4個主要組成部分的職責與功能。

而我們通常所說的jvm組成指的是運行時數據區(Runtime Data Area),因爲通常需要程序員調試分析的區域就是“運行時數據區”,或者更具體的來說就是“運行時數據區”裏面的Heap(堆)模塊,那接下來我們來看運行時數據區(Runtime Data Area)是由哪些模塊組成的。

二、運行時數據區組成
jvm的運行時數據區,不同虛擬機實現可能略微有所不同,但都會遵從Java虛擬機規範,Java虛擬機所管理的內存將會包括以下幾個運行時數據區域:

程序計數器(Program Counter Register)
Java虛擬機棧(Java Virtual Machine Stacks)
本地方法棧(Native Method Stack)
Java堆(Java Heap)
方法區(Methed Area)
接下來我們分別介紹每個區域的用途。

a、Java程序計數器

程序計數器(Program Counter Register)是一塊較小的內存空間,它可以看作是當前線程所執行的字節碼的行號指示器。在虛擬機的概念模型裏,字節碼解析器的工作是通過改變這個計數器的值來選取下一條需要執行的字節碼指令,分支、循環、跳轉、異常處理、線程恢復等基礎功能都需要依賴這個計數器來完成。

特性:內存私有

由於jvm的多線程是通過線程輪流切換並分配處理器執行時間的方式來實現的,也就是任何時刻,一個處理器(或者說一個內核)都只會執行一條線程中的指令。因此爲了線程切換後能恢復到正確的執行位置,每個線程都有獨立的程序計數器。

異常規定:無

如果線程正在執行Java中的方法,程序計數器記錄的就是正在執行虛擬機字節碼指令的地址,如果是Native方法,這個計數器就爲空(undefined),因此該內存區域是唯一一個在Java虛擬機規範中沒有規定OutOfMemoryError的區域。

b、Java虛擬機棧

Java虛擬機棧(Java Virtual Machine Stacks)描述的是Java方法執行的內存模型,每個方法在執行的同時都會創建一個線幀(Stack Frame)用於存儲局部變量表、操作數棧、動態鏈接、方法出口等信息,每個方法從調用直至執行完成的過程,都對應着一個線幀在虛擬機棧中入棧到出棧的過程。

特性:內存私有,它的生命週期和線程相同。

異常規定:StackOverflowError、OutOfMemoryError

1、如果線程請求的棧深度大於虛擬機所允許的棧深度就會拋出StackOverflowError異常。

2、如果虛擬機是可以動態擴展的,如果擴展時無法申請到足夠的內存就會拋出OutOfMemoryError異常。

c、本地方法棧

本地方法棧(Native Method Stack)與虛擬機棧的作用是一樣的,只不過虛擬機棧是服務Java方法的,而本地方法棧是爲虛擬機調用Native方法服務的。

在Java虛擬機規範中對於本地方法棧沒有特殊的要求,虛擬機可以自由的實現它,因此在Sun HotSpot虛擬機直接把本地方法棧和虛擬機棧合二爲一了。

特性和異常: 同虛擬機棧,請參考上面知識點。

d、Java堆

Java堆(Java Heap)是Java虛擬機中內存最大的一塊,是被所有線程共享的,在虛擬機啓動時候創建,Java堆唯一的目的就是存放對象實例,幾乎所有的對象實例都在這裏分配內存,隨着JIT編譯器的發展和逃逸分析技術的逐漸成熟,棧上分配、標量替換優化的技術將會導致一些微妙的變化,所有的對象都分配在堆上漸漸變得不那麼“絕對”了。

特性:內存共享

異常規定:OutOfMemoryError

如果在堆中沒有內存完成實例分配,並且堆不可以再擴展時,將會拋出OutOfMemoryError。

Java虛擬機規範規定,Java堆可以處在物理上不連續的內存空間中,只要邏輯上連續即可,就像我們的磁盤空間一樣。在實現上也可以是固定大小的,也可以是可擴展的,不過當前主流的虛擬機都是可擴展的,通過-Xmx和-Xms控制。

e、方法區

方法區(Methed Area)用於存儲已被虛擬機加載的類信息、常量、靜態變量、即時編譯後的代碼等數據。

誤區:方法區不等於永生代

很多人原因把方法區稱作“永久代”(Permanent Generation),本質上兩者並不等價,只是HotSpot虛擬機垃圾回收器團隊把GC分代收集擴展到了方法區,或者說是用來永久代來實現方法區而已,這樣能省去專門爲方法區編寫內存管理的代碼,但是在Jdk8也移除了“永久代”,使用Native Memory來實現方法區。

特性:內存共享

異常規定:OutOfMemoryError

當方法無法滿足內存分配需求時會拋出OutOfMemoryError異常。

三、總結
本文講了jvm的主要組成部分,以及組成部分中最重要的運行時數據區(Runtime Data Area)的構成,其中程序計數器、虛擬機棧和本地方法爲私有內存,會隨着線程而生,隨着線程而滅,而Java堆作爲最大的內存區域將是開發人員重點關注的內存區域,還有方法區以及運行時常量區與永生代的關係,最後講了直接內存的實現過程已經使用時需要主要的點,希望能夠幫助大家更好的理解jvm。
面試---關於jvm的組成
喜歡的點點關注,點點贊。
對Java技術,架構技術感興趣的朋友,歡迎加QQ羣866865133,一起學習,相互討論。

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章