国产探花免费观看_亚洲丰满少妇自慰呻吟_97日韩有码在线_资源在线日韩欧美_一区二区精品毛片,辰东完美世界有声小说,欢乐颂第一季,yy玄幻小说排行榜完本

首頁 > 編程 > Java > 正文

深入理解Java虛擬機——類加載機制

2019-11-06 07:24:47
字體:
供稿:網(wǎng)友

一 概述

虛擬機把描述類的數(shù)據(jù)從Class文件加載到內(nèi)存,并對數(shù)據(jù)進行校驗、 轉(zhuǎn)換解析和初始化,最終形成可以被虛擬機直接使用的java類型,這就是虛擬機的類加載機制。 

與那些在編譯時需要進行連接工作的語言不同,在Java語言里面,類型的加載、 連接和初始化過程都是在程序運行期間完成的 。

二 類加載的時機

2.1 類的生命周期

圖片來源于《深入理解Java虛擬機》

加載、 驗證、 準(zhǔn)備、 初始化和卸載這5個階段的順序是確定的 ,而解析階段則不一定 ,這是為了支持動態(tài)綁定。

2.2 什么時候開始

什么時候開始加載,Java虛擬機規(guī)范中并沒有進行強制約束,但是對于初始化階段,虛擬機規(guī)范則是嚴格規(guī)定了有且只有5種情況必須立即對類進行“初始化”(而加載、 驗證、 準(zhǔn)備自然需要在此之前開始),以下情況下,若類沒有進行過初始化,則需要觸發(fā)其初始化:

(1)遇到new、getstatic、 putstatic或invokestatic這4條字節(jié)碼指令時。常見場景:使用new關(guān)鍵字實例化對象的時候、 讀取或設(shè)置一個類的靜態(tài)字段(被final修飾、 已在編譯期把結(jié)果放入常量池的靜態(tài)字段除外)的時候,以及調(diào)用一個類的靜態(tài)方法的時候。 

(2)使用java.lang.reflect包的方法對類進行反射調(diào)用的時候 。

(3)當(dāng)初始化一個類的時候,如果發(fā)現(xiàn)其父類還沒有進行過初始化,則需要先觸發(fā)其父類的初始化。 

注意:接口在初始化時,并不要求其父接口全部都完成了初始化,只有在真正使用到父接口的時候(如引用接口中定義的常量)才會初始化。 

(4)當(dāng)虛擬機啟動時,用戶需要指定一個要執(zhí)行的主類(包含main()方法的那個類),虛擬機會先初始化這個主類 。

(5)如果一個java.lang.invoke.MethodHandle實例最后的解析結(jié)果是REF_getStatic、REF_putStatic、 REF_invokeStatic的方法句柄 。

三 類加載的過程

加載過程包括:加載、 驗證、 準(zhǔn)備、 解析和初始化 。

3.1 加載

此階段完成三件事:

(1)通過一個類的全限定名來獲取定義此類的二進制字節(jié)流。

(2)將這個字節(jié)流所代表的靜態(tài)存儲結(jié)構(gòu)轉(zhuǎn)化為方法區(qū)的運行時數(shù)據(jù)結(jié)構(gòu)。

(3)在內(nèi)存中生成一個代表這個類的java.lang.Class對象,作為方法區(qū)這個類的各種數(shù)據(jù)的訪問入口。

加載階段完成后,虛擬機外部的二進制字節(jié)流就按照虛擬機所需的格式存儲在方法區(qū)之中 ,加載階段和連接階段是交叉進行的。

3.2 驗證

目的是為了確保Class文件的字節(jié)流中包含的信息符合當(dāng)前虛擬機的要求,并且不會危害虛擬機自身的安全。 

3.3 準(zhǔn)備

準(zhǔn)備階段是正式為類變量分配內(nèi)存并設(shè)置類變量初始值的階段,這些變量所使用的內(nèi)存都將在方法區(qū)中進行分配。這時候進行內(nèi)存分配的僅包括類變量(被static修飾的變量),而不包括實例變量,實例變量將會在對象實例化時隨著對象一起分配在Java堆中。  

3.4 解析

解析階段是虛擬機將常量池內(nèi)的符號引用替換為直接引用的過程 。

3.5 初始化

到了初始化階段,才真正開始執(zhí)行類中定義的Java程序代碼 。在準(zhǔn)備階段,類變量已經(jīng)賦過一次系統(tǒng)要求的初始值,而在初始化階段,則根據(jù)程序員通過程序制定的主觀計劃去初始化類變量和其他資源 。

四 類加載器

從Java虛擬機的角度來講,只存在兩種不同的類加載器 :一種是啟動類加載器(Bootstrap ClassLoader),這個類加載器使用C++語言實現(xiàn),是虛擬機自身的一部分;另一種就是所有其他的類加載器,這些類加載器都由Java語言實現(xiàn),獨立于虛擬機外部,并且全都繼承自抽象類java.lang.ClassLoader。

Bootstrap ClassLoader :負責(zé)將存放在<JAVA_HOME>/lib目錄中的,或者被-Xbootclasspath參數(shù)所指定的路徑中的,并且是虛擬機識別的類庫加載到虛擬機內(nèi)中。

Bootstrap ClassLoader :負責(zé)加載<JAVA_HOME>/lib/ext目錄中的,或者被java.ext.dirs系統(tǒng)變量所指定的路徑中的所有類庫,開發(fā)者可以直接使用。

application ClassLoader:它負責(zé)加載用戶類路徑(ClassPath)上所指定的類庫,開發(fā)者可以直接使用這個類加載器,如果應(yīng)用程序中沒有自定義過自己的類加載器,一般情況下這個就是程序中默認的類加載器。

五 雙親委派模型 

來源于《深入理解Java虛擬機》

如果一個類加載器收到了類加載的請求,它首先不會自己去嘗試加載這個類,而是把這個請求委派給父類加載器去完成,每一個層次的類加載器都是如此,因此所有的加載請求最終都應(yīng)該傳送到頂層的啟動類加載器中,只有當(dāng)父加載器反饋自己無法完成這個加載請求(它的搜索范圍中沒有找到所需的類)時,子加載器才會嘗試自己去加載。


發(fā)表評論 共有條評論
用戶名: 密碼:
驗證碼: 匿名發(fā)表
主站蜘蛛池模板: 临猗县| 方正县| 泗洪县| 神池县| 玉环县| 墨玉县| 沂源县| 德令哈市| 哈尔滨市| 岳普湖县| 长海县| 漳平市| 齐齐哈尔市| 平泉县| 建平县| 兖州市| 淳安县| 黑河市| 铁岭市| 马边| 龙南县| 玛多县| 乾安县| 安丘市| 如东县| 芜湖县| 塔河县| 武邑县| 虎林市| 福鼎市| 晋城| 隆林| 小金县| 宁南县| 商城县| 莫力| 海兴县| 扶沟县| 梁平县| 惠来县| 越西县|