1. 程式人生 > 其它 >JVM第一節:類載入機制【熊的學習之路】

JVM第一節:類載入機制【熊的學習之路】

一、程式是如何跑起來的

我們編寫的Java檔案並不會直接被JVM載入,而是先通過Javac命令編譯成class檔案後,才能夠被JVM載入,載入後通過我們程式碼中的資訊去給物件,類資訊等賦予空間去儲存,還會有執行引擎去按照我們的程式碼去執行,程式計數器去記錄程式碼執行的行標數,並有垃圾回收器不時的去回收不再使用的物件

二、類的載入過程

一個類在進入JVM會經歷以下過程:載入→校驗→準備→解析→初始化

校驗

校驗是對被載入進來的class檔案做一次檢查,例如,去檢查位元組碼是否符合規範,保證JVM可以正常執行該class檔案

準備

準備就是給被載入的類開闢空間,並且給類物件(也就是static定義的變數)分配空間,並且賦值初始值,例如:

如上圖類,在準備階段,會給類變數i 分配空間,並賦值為0,注意!,此處不是賦值為3,這裡的初始值指的是預設初始值,該0的為0,該為null的為null

解析

解析階段是將物件變數變成實體地址,JVM並不認識我們的變數名,如果不變成實體地址的話,JVM就不能進行操作

初始化

這裡的初始化,才是用我們建立變數時給的初始值去進行賦值,例如上圖中給靜態變數賦值為3的操作,是在這個階段去進行賦值的,注意!在此處涉及到物件的初始化,會首先去完成該物件所屬類的載入→校驗→準備→解析→初始化操作,如下圖

在Start類的初始化階段去建立了User類的例項,所以在此時也會觸發對User類的載入等操作。

下圖用一張圖來說明以上過程

載入

我們寫的程式中的類並不是一次性被全部載入的,只有用到時才會被載入,main()是程式的入口,所以,main()方法所在的類會第一時間被載入

如上圖程式碼中,main()方法在Start類中,所以Start類首先被載入,並執行校驗→準備→解析→初始化,在初始化階段我們發現該類main()方法中建立了Cat類的例項物件,所以,Cat類也會被載入

若Cat有父類,如下圖:

那麼,在載入Cat類之前會首先完成對其父類Animal類的載入,如下是以圖片來展示這一流程

類載入器

Java有如下類載入器

啟動類載入器 (Bootstrap ClassLoader):載入jdk中lib目錄下的類,此處為核心類庫

擴充套件類載入器(ExtensionClassLoader):載入lib\ext目錄下的類

系統類載入器(ApplicationClassLoader):載入自己寫的類

自定義類載入器:由自己去實現類載入器

雙親委派機制

當一個類需要被載入時,系統類載入器首先會檢視自己是否載入過此類,要是已經載入過了,那麼會直接返回,若沒載入過,則向上詢問父類——擴充套件類載入器,擴充套件類載入器也會檢視自己是否載入過該類,若載入過,則返回,若沒載入過,則向上詢問父類——啟動類載入器,啟動類載入器也會進行同樣的檢查,若啟動類載入器都沒有載入過該類,那麼啟動類載入器會檢視是否可以載入該類,若無法載入,則向下詢問擴充套件類載入器,一直詢問到系統類載入器都無法載入該類,則會檢視自定義的類載入器是否可以載入該類,若所有的類載入器都無法載入該類,那麼就會報ClassNotFundException,雙親委派機制如下圖:

雙親委派機制的優點:防止重複載入、保證核心類不被破壞