真实的国产乱ⅩXXX66竹夫人,五月香六月婷婷激情综合,亚洲日本VA一区二区三区,亚洲精品一区二区三区麻豆

成都創(chuàng)新互聯(lián)網(wǎng)站制作重慶分公司

Java中如何使用ClassLoader類(lèi)加載器

Java中如何使用ClassLoader類(lèi)加載器,相信很多沒(méi)有經(jīng)驗(yàn)的人對(duì)此束手無(wú)策,為此本文總結(jié)了問(wèn)題出現(xiàn)的原因和解決方法,通過(guò)這篇文章希望你能解決這個(gè)問(wèn)題。

創(chuàng)新互聯(lián)專(zhuān)注于企業(yè)成都全網(wǎng)營(yíng)銷(xiāo)推廣、網(wǎng)站重做改版、吐魯番網(wǎng)站定制設(shè)計(jì)、自適應(yīng)品牌網(wǎng)站建設(shè)、H5高端網(wǎng)站建設(shè)、成都做商城網(wǎng)站、集團(tuán)公司官網(wǎng)建設(shè)、外貿(mào)網(wǎng)站制作、高端網(wǎng)站制作、響應(yīng)式網(wǎng)頁(yè)設(shè)計(jì)等建站業(yè)務(wù),價(jià)格優(yōu)惠性?xún)r(jià)比高,為吐魯番等各大城市提供網(wǎng)站開(kāi)發(fā)制作服務(wù)。

一、類(lèi)加載過(guò)程

1.加載

加載指的是將類(lèi)的class文件讀入到內(nèi)存,并為之創(chuàng)建一個(gè)java.lang.Class對(duì)象,也就是說(shuō),當(dāng)程序中使用任何類(lèi)時(shí),系統(tǒng)都會(huì)為之建立一個(gè)java.lang.Class對(duì)象。

類(lèi)的加載由類(lèi)加載器完成,類(lèi)加載器通常由JVM提供,這些類(lèi)加載器也是前面所有程序運(yùn)行的基礎(chǔ),JVM提供的這些類(lèi)加載器通常被稱(chēng)為系統(tǒng)類(lèi)加載器。除此之外,開(kāi)發(fā)者可以通過(guò)繼承ClassLoader基類(lèi)來(lái)創(chuàng)建自己的類(lèi)加載器。

通過(guò)使用不同的類(lèi)加載器,可以從不同來(lái)源加載類(lèi)的二進(jìn)制數(shù)據(jù),通常有如下幾種來(lái)源。

從本地文件系統(tǒng)加載class文件,這是前面絕大部分示例程序的類(lèi)加載方式。從JAR包加載class文件,這種方式也是很常見(jiàn)的,前面介紹JDBC編程時(shí)用到的數(shù)據(jù)庫(kù)驅(qū)動(dòng)類(lèi)就放在JAR文件中,JVM可以從JAR文件中直接加載該class文件。通過(guò)網(wǎng)絡(luò)加載class文件。把一個(gè)Java源文件動(dòng)態(tài)編譯,并執(zhí)行加載。類(lèi)加載器通常無(wú)須等到“首次使用”該類(lèi)時(shí)才加載該類(lèi),Java虛擬機(jī)規(guī)范允許系統(tǒng)預(yù)先加載某些類(lèi)。

2.鏈接

當(dāng)類(lèi)被加載之后,系統(tǒng)為之生成一個(gè)對(duì)應(yīng)的Class對(duì)象,接著將會(huì)進(jìn)入連接階段,連接階段負(fù)責(zé)把類(lèi)的二進(jìn)制數(shù)據(jù)合并到JRE中。類(lèi)連接又可分為如下3個(gè)階段。

1)驗(yàn)證:驗(yàn)證階段用于檢驗(yàn)被加載的類(lèi)是否有正確的內(nèi)部結(jié)構(gòu),并和其他類(lèi)協(xié)調(diào)一致。Java是相對(duì)C++語(yǔ)言是安全的語(yǔ)言,例如它有C++不具有的數(shù)組越界的檢查。這本身就是對(duì)自身安全的一種保護(hù)。驗(yàn)證階段是Java非常重要的一個(gè)階段,它會(huì)直接的保證應(yīng)用是否會(huì)被惡意入侵的一道重要的防線(xiàn),越是嚴(yán)謹(jǐn)?shù)尿?yàn)證機(jī)制越安全。驗(yàn)證的目的在于確保Class文件的字節(jié)流中包含信息符合當(dāng)前虛擬機(jī)要求,不會(huì)危害虛擬機(jī)自身安全。其主要包括四種驗(yàn)證,文件格式驗(yàn)證,元數(shù)據(jù)驗(yàn)證,字節(jié)碼驗(yàn)證,符號(hào)引用驗(yàn)證。

四種驗(yàn)證做進(jìn)一步說(shuō)明:

文件格式驗(yàn)證:主要驗(yàn)證字節(jié)流是否符合Class文件格式規(guī)范,并且能被當(dāng)前的虛擬機(jī)加載處理。例如:主,次版本號(hào)是否在當(dāng)前虛擬機(jī)處理的范圍之內(nèi)。常量池中是否有不被支持的常量類(lèi)型。指向常量的中的索引值是否存在不存在的常量或不符合類(lèi)型的常量。

元數(shù)據(jù)驗(yàn)證:對(duì)字節(jié)碼描述的信息進(jìn)行語(yǔ)義的分析,分析是否符合java的語(yǔ)言語(yǔ)法的規(guī)范。

字節(jié)碼驗(yàn)證:最重要的驗(yàn)證環(huán)節(jié),分析數(shù)據(jù)流和控制,確定語(yǔ)義是合法的,符合邏輯的。主要的針對(duì)元數(shù)據(jù)驗(yàn)證后對(duì)方法體的驗(yàn)證。保證類(lèi)方法在運(yùn)行時(shí)不會(huì)有危害出現(xiàn)。

符號(hào)引用驗(yàn)證:主要是針對(duì)符號(hào)引用轉(zhuǎn)換為直接引用的時(shí)候,是會(huì)延伸到第三解析階段,主要去確定訪(fǎng)問(wèn)類(lèi)型等涉及到引用的情況,主要是要保證引用一定會(huì)被訪(fǎng)問(wèn)到,不會(huì)出現(xiàn)類(lèi)等無(wú)法訪(fǎng)問(wèn)的問(wèn)題。

2)準(zhǔn)備:類(lèi)準(zhǔn)備階段負(fù)責(zé)為類(lèi)的靜態(tài)變量分配內(nèi)存,并設(shè)置默認(rèn)初始值。

3)解析:將類(lèi)的二進(jìn)制數(shù)據(jù)中的符號(hào)引用替換成直接引用。說(shuō)明一下:符號(hào)引用:符號(hào)引用是以一組符號(hào)來(lái)描述所引用的目標(biāo),符號(hào)可以是任何的字面形式的字面量,只要不會(huì)出現(xiàn)沖突能夠定位到就行。布局和內(nèi)存無(wú)關(guān)。直接引用:是指向目標(biāo)的指針,偏移量或者能夠直接定位的句柄。該引用是和內(nèi)存中的布局有關(guān)的,并且一定加載進(jìn)來(lái)的。

3.初始化

初始化是為類(lèi)的靜態(tài)變量賦予正確的初始值,準(zhǔn)備階段和初始化階段看似有點(diǎn)矛盾,其實(shí)是不矛盾的,如果類(lèi)中有語(yǔ)句:private static int a = 10,它的執(zhí)行過(guò)程是這樣的,首先字節(jié)碼文件被加載到內(nèi)存后,先進(jìn)行鏈接的驗(yàn)證這一步驟,驗(yàn)證通過(guò)后準(zhǔn)備階段,給a分配內(nèi)存,因?yàn)樽兞縜是static的,所以此時(shí)a等于int類(lèi)型的默認(rèn)初始值0,即a=0,然后到解析(后面在說(shuō)),到初始化這一步驟時(shí),才把a(bǔ)的真正的值10賦給a,此時(shí)a=10。

二、類(lèi)加載時(shí)機(jī)

創(chuàng)建類(lèi)的實(shí)例,也就是new一個(gè)對(duì)象訪(fǎng)問(wèn)某個(gè)類(lèi)或接口的靜態(tài)變量,或者對(duì)該靜態(tài)變量賦值調(diào)用類(lèi)的靜態(tài)方法反射(Class.forName("com.lyj.load"))初始化一個(gè)類(lèi)的子類(lèi)(會(huì)首先初始化子類(lèi)的父類(lèi))JVM啟動(dòng)時(shí)標(biāo)明的啟動(dòng)類(lèi),即文件名和類(lèi)名相同的那個(gè)類(lèi)

除此之外,下面幾種情形需要特別指出:

對(duì)于一個(gè)final類(lèi)型的靜態(tài)變量,如果該變量的值在編譯時(shí)就可以確定下來(lái),那么這個(gè)變量相當(dāng)于“宏變量”。Java編譯器會(huì)在編譯時(shí)直接把這個(gè)變量出現(xiàn)的地方替換成它的值,因此即使程序使用該靜態(tài)變量,也不會(huì)導(dǎo)致該類(lèi)的初始化。反之,如果final類(lèi)型的靜態(tài)Field的值不能在編譯時(shí)確定下來(lái),則必須等到運(yùn)行時(shí)才可以確定該變量的值,如果通過(guò)該類(lèi)來(lái)訪(fǎng)問(wèn)它的靜態(tài)變量,則會(huì)導(dǎo)致該類(lèi)被初始化。

三、類(lèi)加載器

類(lèi)加載器負(fù)責(zé)加載所有的類(lèi),其為所有被載入內(nèi)存中的類(lèi)生成一個(gè)java.lang.Class實(shí)例對(duì)象。一旦一個(gè)類(lèi)被加載如JVM中,同一個(gè)類(lèi)就不會(huì)被再次載入了。正如一個(gè)對(duì)象有一個(gè)唯一的標(biāo)識(shí)一樣,一個(gè)載入JVM的類(lèi)也有一個(gè)唯一的標(biāo)識(shí)。在Java中,一個(gè)類(lèi)用其全限定類(lèi)名(包括包名和類(lèi)名)作為標(biāo)識(shí);但在JVM中,一個(gè)類(lèi)用其全限定類(lèi)名和其類(lèi)加載器作為其唯一標(biāo)識(shí)。例如,如果在pg的包中有一個(gè)名為Person的類(lèi),被類(lèi)加載器ClassLoader的實(shí)例kl負(fù)責(zé)加載,則該P(yáng)erson類(lèi)對(duì)應(yīng)的Class對(duì)象在JVM中表示為(Person.pg.kl)。這意味著兩個(gè)類(lèi)加載器加載的同名類(lèi):(Person.pg.kl)和(Person.pg.kl2)是不同的、它們所加載的類(lèi)也是完全不同、互不兼容的。

JVM預(yù)定義有三種類(lèi)加載器,當(dāng)一個(gè) JVM啟動(dòng)的時(shí)候,Java開(kāi)始使用如下三種類(lèi)加載器:

1)根類(lèi)加載器(bootstrap class loader):它用來(lái)加載 Java 的核心類(lèi),是用原生代碼來(lái)實(shí)現(xiàn)的,并不繼承自 java.lang.ClassLoader(負(fù)責(zé)加載$JAVA_HOME中jre/lib/rt.jar里所有的class,由C++實(shí)現(xiàn),不是ClassLoader子類(lèi))。由于引導(dǎo)類(lèi)加載器涉及到虛擬機(jī)本地實(shí)現(xiàn)細(xì)節(jié),開(kāi)發(fā)者無(wú)法直接獲取到啟動(dòng)類(lèi)加載器的引用,所以不允許直接通過(guò)引用進(jìn)行操作。

下面程序可以獲得根類(lèi)加載器所加載的核心類(lèi)庫(kù),并會(huì)看到本機(jī)安裝的Java環(huán)境變量指定的jdk中提供的核心jar包路徑:

public class ClassLoaderTest {  public static void main(String[] args) {    URL[] urls = sun.misc.Launcher.getBootstrapClassPath().getURLs();    for(URL url : urls){      System.out.println(url.toExternalForm());    }  }}

運(yùn)行結(jié)果:

2)擴(kuò)展類(lèi)加載器(extensions class loader):它負(fù)責(zé)加載JRE的擴(kuò)展目錄,lib/ext或者由java.ext.dirs系統(tǒng)屬性指定的目錄中的JAR包的類(lèi)。由Java語(yǔ)言實(shí)現(xiàn),父類(lèi)加載器為null。

3)系統(tǒng)類(lèi)加載器(system class loader):被稱(chēng)為系統(tǒng)(也稱(chēng)為應(yīng)用)類(lèi)加載器,它負(fù)責(zé)在JVM啟動(dòng)時(shí)加載來(lái)自Java命令的-classpath選項(xiàng)、java.class.path系統(tǒng)屬性,或者CLASSPATH換將變量所指定的JAR包和類(lèi)路徑。程序可以通過(guò)ClassLoader的靜態(tài)方法getSystemClassLoader()來(lái)獲取系統(tǒng)類(lèi)加載器。如果沒(méi)有特別指定,則用戶(hù)自定義的類(lèi)加載器都以此類(lèi)加載器作為父加載器。由Java語(yǔ)言實(shí)現(xiàn),父類(lèi)加載器為ExtClassLoader。

類(lèi)加載器加載Class大致要經(jīng)過(guò)如下8個(gè)步驟:

檢測(cè)此Class是否載入過(guò),即在緩沖區(qū)中是否有此Class,如果有直接進(jìn)入第8步,否則進(jìn)入第2步。如果沒(méi)有父類(lèi)加載器,則要么Parent是根類(lèi)加載器,要么本身就是根類(lèi)加載器,則跳到第4步,如果父類(lèi)加載器存在,則進(jìn)入第3步。請(qǐng)求使用父類(lèi)加載器去載入目標(biāo)類(lèi),如果載入成功則跳至第8步,否則接著執(zhí)行第5步。請(qǐng)求使用根類(lèi)加載器去載入目標(biāo)類(lèi),如果載入成功則跳至第8步,否則跳至第7步。當(dāng)前類(lèi)加載器嘗試尋找Class文件,如果找到則執(zhí)行第6步,如果找不到則執(zhí)行第7步。從文件中載入Class,成功后跳至第8步。拋出ClassNotFountException異常。返回對(duì)應(yīng)的java.lang.Class對(duì)象。

四、類(lèi)加載機(jī)制:

1.JVM的類(lèi)加載機(jī)制主要有如下3種。

全盤(pán)負(fù)責(zé):所謂全盤(pán)負(fù)責(zé),就是當(dāng)一個(gè)類(lèi)加載器負(fù)責(zé)加載某個(gè)Class時(shí),該Class所依賴(lài)和引用其他Class也將由該類(lèi)加載器負(fù)責(zé)載入,除非顯示使用另外一個(gè)類(lèi)加載器來(lái)載入。雙親委派:所謂的雙親委派,則是先讓父類(lèi)加載器試圖加載該Class,只有在父類(lèi)加載器無(wú)法加載該類(lèi)時(shí)才嘗試從自己的類(lèi)路徑中加載該類(lèi)。通俗的講,就是某個(gè)特定的類(lèi)加載器在接到加載類(lèi)的請(qǐng)求時(shí),首先將加載任務(wù)委托給父加載器,依次遞歸,如果父加載器可以完成類(lèi)加載任務(wù),就成功返回;只有父加載器無(wú)法完成此加載任務(wù)時(shí),才自己去加載。緩存機(jī)制。緩存機(jī)制將會(huì)保證所有加載過(guò)的Class都會(huì)被緩存,當(dāng)程序中需要使用某個(gè)Class時(shí),類(lèi)加載器先從緩存區(qū)中搜尋該Class,只有當(dāng)緩存區(qū)中不存在該Class對(duì)象時(shí),系統(tǒng)才會(huì)讀取該類(lèi)對(duì)應(yīng)的二進(jìn)制數(shù)據(jù),并將其轉(zhuǎn)換成Class對(duì)象,存入緩沖區(qū)中。這就是為很么修改了Class后,必須重新啟動(dòng)JVM,程序所做的修改才會(huì)生效的原因。2.這里說(shuō)明一下雙親委派機(jī)制:

雙親委派機(jī)制,其工作原理的是,如果一個(gè)類(lèi)加載器收到了類(lèi)加載請(qǐng)求,它并不會(huì)自己先去加載,而是把這個(gè)請(qǐng)求委托給父類(lèi)的加載器去執(zhí)行,如果父類(lèi)加載器還存在其父類(lèi)加載器,則進(jìn)一步向上委托,依次遞歸,請(qǐng)求最終將到達(dá)頂層的啟動(dòng)類(lèi)加載器,如果父類(lèi)加載器可以完成類(lèi)加載任務(wù),就成功返回,倘若父類(lèi)加載器無(wú)法完成此加載任務(wù),子加載器才會(huì)嘗試自己去加載,這就是雙親委派模式,即每個(gè)兒子都很懶,每次有活就丟給父親去干,直到父親說(shuō)這件事我也干不了時(shí),兒子自己才想辦法去完成。

雙親委派機(jī)制的優(yōu)勢(shì):

采用雙親委派模式的是好處是Java類(lèi)隨著它的類(lèi)加載器一起具備了一種帶有優(yōu)先級(jí)的層次關(guān)系,通過(guò)這種層級(jí)關(guān)可以避免類(lèi)的重復(fù)加載,當(dāng)父親已經(jīng)加載了該類(lèi)時(shí),就沒(méi)有必要子ClassLoader再加載一次。其次是考慮到安全因素,java核心api中定義類(lèi)型不會(huì)被隨意替換,假設(shè)通過(guò)網(wǎng)絡(luò)傳遞一個(gè)名為java.lang.Integer的類(lèi),通過(guò)雙親委托模式傳遞到啟動(dòng)類(lèi)加載器,而啟動(dòng)類(lèi)加載器在核心Java API發(fā)現(xiàn)這個(gè)名字的類(lèi),發(fā)現(xiàn)該類(lèi)已被加載,并不會(huì)重新加載網(wǎng)絡(luò)傳遞的過(guò)來(lái)的java.lang.Integer,而直接返回已加載過(guò)的Integer.class,這樣便可以防止核心API庫(kù)被隨意篡改。

看完上述內(nèi)容,你們掌握J(rèn)ava中如何使用ClassLoader類(lèi)加載器的方法了嗎?如果還想學(xué)到更多技能或想了解更多相關(guān)內(nèi)容,歡迎關(guān)注創(chuàng)新互聯(lián)行業(yè)資訊頻道,感謝各位的閱讀!


網(wǎng)站名稱(chēng):Java中如何使用ClassLoader類(lèi)加載器
本文地址:http://weahome.cn/article/ggdoii.html

其他資訊

在線(xiàn)咨詢(xún)

微信咨詢(xún)

電話(huà)咨詢(xún)

028-86922220(工作日)

18980820575(7×24)

提交需求

返回頂部