1. 程式人生 > >JAVA虛擬機器JVM工作原理

JAVA虛擬機器JVM工作原理

JAVA虛擬機器JVM工作原理

 

 https://blog.csdn.net/leftfist/article/details/85131366

提起JAVA,都知道它有個虛擬機器,因此可以跨平臺,一次編寫,到處執行。但具體原理是咋樣的?身為JAVA小白,豈可不知!

一、原理
二、結構
1、類載入器
2、執行引擎
3、執行時資料區域
  • 1
  • 2
  • 3
  • 4
  • 5

一、原理
JVM實現了JAVA語言最重要的特徵:平臺無關性。其原理:java程式並不直接在作業系統上執行,而是由JVM執行。JVM遮蔽了與具體平臺相關的資訊,使得JAVA程式只需編譯成適應JVM,可以在JVM上執行的目的碼(.class)就行,JVM再負責解釋成具體平臺的機器指令執行。同時,JVM還會進行安全檢查,是java程式的安全檢驗引擎。

二、結構
JVM由三大部分組成:

1、類載入器
2、執行引擎
3、執行時資料區域
  • 1
  • 2
  • 3

在這裡插入圖片描述

1、類載入器
具體作用就是將.class檔案載入到jvm虛擬機器中去,程式就可以正確運行了。但是,jvm啟動的時候,並不會一次性載入所有的.class檔案,而是根據需要去動態載入。

類的載入過程採用雙親委派模型:

1)當前類載入器首先檢查自己的載入清單,如果存在該類,則返回之;

2)如果沒找到,委託父類載入器去載入;父類載入器重複動作1,遞迴至祖宗bootstrap ClassLoder(我靠,bootstrap,還以為是前端框架呢。bootstrap,引導之意);

3)都沒有,仍然由當前類載入器載入,並納入自己快取中。
  • 1
  • 2
  • 3
  • 4
  • 5

採用雙親委派模型,目的在於更好的保證Java平臺的安全。所謂的安全,是指java的核心類被使用者自己編寫的類所替換。由於核心類在虛擬機器初始化時就已載入,而每次載入類前先檢查是否存在,所以可以避免核心類被替換。

各種類載入器:
在這裡插入圖片描述
Bootstrap class loader: 父類
當執行 java 虛擬機器時,這個類載入器被建立,它負責載入虛擬機器的核心類庫,如 java.lang.* 等。例如 java.lang.Object 就是由根類載入器載入的。需要注意的是,這個類載入器不是用 java 語言寫的,而是用 C/C++ 寫的。

Extension class loader:
這個載入器加載出了基本 API 之外的一些拓展類。

AppClass Loader(SystemAppClass):
載入應用程式和程式設計師自定義的類。

2、執行引擎
作用: 執行java編譯好的位元組碼,或者執行本地方法

3、執行時資料區域
JVM 執行時資料區域 (JVM Runtime Area) 其實就是指 JVM 在執行期間,其對JVM記憶體空間的劃分和分配。JVM在執行時將資料劃分為6個區域來儲存:

Program Counter (PC) Register:程式計數器

Java Virtual Machine Stacks:Java虛擬機器棧

Heap Memory:堆記憶體

Method Area:方法區

Run-time Constant Pool:執行時常量池

Native Method Stacks:本地方法棧
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11

在這裡插入圖片描述

我們寫的所有程式都被載入到這裡,按不同類別存放在

堆記憶體
Java虛擬機器棧
本地方法棧
程式計數器
方法區
  • 1
  • 2
  • 3
  • 4
  • 5

1)從執行緒的角度理解Java Runtime Area

a.執行緒私有:
程式計數器 Java虛擬機器棧 本地方法棧,生命週期與執行緒一致;

這3個記憶體區域是不需要進行垃圾回收的。因為他們的生命週期是和執行緒同步的,隨著執行緒的銷燬,他們佔用的記憶體會自動釋放。

b.執行緒共享:
堆記憶體,方法區,執行時常量池,生命週期與JVM一致。

方法區堆記憶體需要進行垃圾回收,回收的物件就是那些不存在任何引用的物件。

2)從儲存內容理解Java Runtime Area

方法區常量池儲存類的資訊

堆記憶體儲存物件資訊

程式計數器Java虛擬機器棧本地方法棧儲存執行緒的資訊

3)堆記憶體、方法區和執行時常量
方法區的作用是儲存 Java 類的結構資訊,當我們建立物件例項後,物件的型別資訊儲存在方法堆之中,例項資料存放在堆記憶體中;

執行時常量池是方法區的一部分,所以也是全域性共享的。其作用是儲存 Java 類檔案常量池中的符號資訊。

class 檔案中存在常量池(非執行時常量池),其在編譯階段就已經確定;JVM 規範對 class 檔案結構有著嚴格的規範,必須符合此規範的 class 檔案才會被 JVM 認可和裝載。
執行時常量池 中儲存著一些 class 檔案中描述的符號引用,同時還會將這些符號引用所翻譯出來的直接引用儲存在 執行時常量池 中。
執行時常量池相對於 class 常量池一大特徵就是其具有動態性,Java 規範並不要求常量只能在執行時才產生,也就是說執行時常量池中的內容並不全部來自 class 常量池,class 常量池並非執行時常量池的唯一資料輸入口;在執行時可以通過程式碼生成常量並將其放入執行時常量池中。
同方法區一樣,當執行時常量池無法申請到新的記憶體時,將丟擲 OutOfMemoryError 異常。

4)直接記憶體(Direct Memory)
直接記憶體並不是JVM管理的記憶體,而是JVM以外的機器記憶體。比如,你有4G的記憶體,JVM佔用了1G,則其餘的3G就是直接記憶體。

JDK中有一種基於通道(Channel)和緩衝區(Buffer)的記憶體分配方式,將由C語言實現的native函式庫分配在直接記憶體中,用儲存在JVM堆中的DirectByteBuffer來引用。由於直接記憶體收到本機器記憶體的限制,所以也可能出現OutOfMemoryError的異常