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

首頁(yè) > 學(xué)院 > 開(kāi)發(fā)設(shè)計(jì) > 正文

Java Se:自定義ClassLoader

2019-11-14 22:13:06
字體:
來(lái)源:轉(zhuǎn)載
供稿:網(wǎng)友
java Se:自定義ClassLoader

JVM是如何知道java.lang包中的類的?JVM又是如何知道我們應(yīng)用中的類的?我們的應(yīng)用中明明是有某個(gè)類, 但是JVM卻拋出ClassNotFoundException,這是為什么?XxxImpl類已經(jīng)實(shí)現(xiàn)了接口Xxx,但是卻拋出XxxImpl does not extend from Xxx,這是為什么?使用類型轉(zhuǎn)換時(shí),可能會(huì)拋出 aa.bb.cc.XXX can not cast to aa.bb.cc,這又是為什么?等等諸多看似詭異情況,其實(shí)都是因?yàn)镃lassLoader。

了解反射的人都知道每一個(gè)類都有一個(gè)Class對(duì)象與之對(duì)應(yīng),那么這個(gè)Class對(duì)象又是哪來(lái)的呢?

如果要了解Class的基本知識(shí),可以參考:

http://blog.csdn.net/irelandken/article/details/7048817http://tyrion.VEvb.com/blog/1958814http://www.blogjava.net/lihuaxajh/articles/94371.htmlhttp://www.javaworld.com/article/2077332/core-java/get-a-load-of-that-name.htmlhttp://www.javaworld.com/article/2075796/java-platform/java-101--class-and-object-initialization.html

我對(duì)ClassLoader的理解

下面是我看了這些博客、文章后,并自定義了一個(gè)ClassLoader進(jìn)行測(cè)試后的理解:

1)ClassLoader加載一個(gè)類時(shí),不會(huì)加載類中所有的類,而是在運(yùn)行時(shí)根據(jù)要使用的類動(dòng)態(tài)加載的,即按需加載。

2)ClassLoader加載一個(gè)類時(shí),也會(huì)加載其父類(包括接口)

3)當(dāng)前類A在運(yùn)行時(shí),類中要使用的其它的類(B,C,D類等),默認(rèn)是由當(dāng)前類A的加載器來(lái)加載的。

4)類型強(qiáng)制轉(zhuǎn)換時(shí),先判定是不是同一個(gè)類加載器,如果不是,就不能進(jìn)行轉(zhuǎn)換。一個(gè)對(duì)象A但往由BootstrapCLassLoader加載的類(A的父類或者接口)轉(zhuǎn)換時(shí),好像不遵循這個(gè)過(guò)程。

5)Thread#contextClassLoader可以用于在切換類加載器。

6)默認(rèn)情況下,線程的上下文加載器采用的與父線程的上下文加載器是同一個(gè)。

7)Class.forName(“xxx”)、Xxx.class 的加載器,使用的都是當(dāng)前類的類加載器。

下面是自定義類加載器代碼清單:

下面就對(duì)這些類做一個(gè)簡(jiǎn)單的說(shuō)明:

StringUtil.java

StringUtil中只有兩個(gè)方法,用于判斷字符串空值。寫這個(gè)類實(shí)在是沒(méi)有必要,但是在測(cè)試中也可以看到效果的。

DebugUtil.java

只是為了打出一些信息。

Person.java

這是一個(gè)典型的Java Bean,沒(méi)有什么可說(shuō)的。

ClassLoaderTestRunner.java

這是業(yè)務(wù)類。從代碼上看也是很簡(jiǎn)單的,只是加載了Person類,創(chuàng)建一個(gè)Person對(duì)象,輸出一些信息。

這個(gè)類 既可以使用系統(tǒng)默認(rèn)的類加載器加載測(cè)試(main方法),也可以使用自定義的類加載器來(lái)測(cè)試。

自定義ClassLoader

目前常用的加載機(jī)制有兩種:委托加載機(jī)制、子類優(yōu)先加載

1)委托加載機(jī)制loadClass()的流程:

(1) 判斷是否已經(jīng)加載這個(gè)類

(2) 如果沒(méi)有加載,當(dāng)前類加載器的父加載器加載,即執(zhí)行l(wèi)oadClass()方法。

(3) 如果當(dāng)前類加載器的所有父加載器都沒(méi)有加載到就讓當(dāng)前加載器調(diào)用 findClass()加載。

2)子類優(yōu)先加載器的流程:

(1) 判斷是否已經(jīng)加載這個(gè)類

(2) 當(dāng)前類加載器直接加載類

(3) 加載不到才走父類加載流程。

JDK中默認(rèn)的加載方式是1),也就是委托加載機(jī)制。

自定義類加載器,一般會(huì)重寫loadClass、findClass。

delegate字段是用于指定是否使用默認(rèn)的委托加載機(jī)制。

這是自定義的加載類的方法。流程是:

1)判斷該加載器是否已經(jīng)加載了這個(gè)類,為了避免重復(fù)的加載。

2)如果delegate=true,委托加載,就使用默認(rèn)的加載方式。

3)如果delegate=false, 排除受保護(hù)的類,然后使用下面的自定義的findClass來(lái)加載類。上述過(guò)程如果出現(xiàn)了異常,仍然會(huì)使用默認(rèn)的加載方法。

findClass是根據(jù)類名加載并定義一個(gè)Class對(duì)象。這個(gè)方法寫的很粗糙,只是為了測(cè)試ClassLoader。

接下來(lái)就可以使用ClassLoaderTest.java來(lái)測(cè)試了:

關(guān)于這個(gè)測(cè)試的簡(jiǎn)單說(shuō)明:

1)這個(gè)測(cè)試中的相關(guān)類,如String, UrlClassLoader, ClassLoader,Object, Thread,Runnable,Exception等都是由默認(rèn)的系統(tǒng)加載器(SystemClassLoader)或者其父類(ExtClassLoader、BootstrapClassLoader)來(lái)加載的。當(dāng)前這個(gè)運(yùn)行時(shí),這個(gè)類(ClassLoaderTest)的加載器是SystemClassLoader。

2)加載ClassLoaderTestRunner類時(shí),使用的自定義的類加載器(也就是SystemClassLoader的子加載器)。加載ClassLoaderTestRunner類時(shí),還會(huì)加載其父類,也就是Object類和Runable接口。

3)這個(gè)測(cè)試執(zhí)行的過(guò)程:

(1) 創(chuàng)建一個(gè)自定義加載器實(shí)例,指定其父加載器為系統(tǒng)加載器。

(2) 加載類ClassLoaderTestRunner。

(3) 啟動(dòng)一個(gè)線程執(zhí)行相關(guān)任務(wù)。

4)根據(jù)上述所說(shuō),如果將Object task = myAppClassLoader .loadClass( classFullName) . newInstance();

改為:

ClassLoaderRunner task= (ClassLoaderRunner) myAppClassLoader. loadClass( classFullName ) . newInstance();就會(huì)出錯(cuò)。

ClassLoaderRunner 是系統(tǒng)加載器加載的,myAppClassLoader是一個(gè)自定義加載器。所以兩者不能進(jìn)行類型的轉(zhuǎn)換。

如果直接在這個(gè)類中使用自定義類加載器來(lái)加載Person類,也會(huì)出現(xiàn)錯(cuò)誤。

如果有興趣的話,可以根據(jù)我上面總結(jié)的內(nèi)容,已經(jīng)我的這個(gè)測(cè)試,自己分析一下子線程t執(zhí)行過(guò)程中,哪些類是被自定義的類加載器加載的,哪些類是被系統(tǒng)加載器加載的,上述task執(zhí)行的結(jié)果是什么?

如果有不理解的也可以參考:

參考

http://blog.csdn.net/irelandken/article/details/7048817

http://tyrion.VEvb.com/blog/1958814

http://www.blogjava.net/lihuaxajh/articles/94371.html

http://www.javaworld.com/article/2077332/core-java/get-a-load-of-that-name.html

http://www.javaworld.com/article/2075796/java-platform/java-101--class-and-object-initialization.html


發(fā)表評(píng)論 共有條評(píng)論
用戶名: 密碼:
驗(yàn)證碼: 匿名發(fā)表
主站蜘蛛池模板: 阿荣旗| 聊城市| 夏河县| 佛坪县| 普陀区| 遵化市| 德昌县| 慈利县| 陇南市| 常州市| 孝昌县| 大足县| 尉犁县| 武山县| 芜湖市| 泰来县| 鹤岗市| 陆河县| 呼和浩特市| 新源县| 宁波市| 大同县| 凤冈县| 德兴市| 华亭县| 金华市| 诸城市| 永平县| 永宁县| 文登市| 罗田县| 高陵县| 裕民县| 枝江市| 万安县| 阳高县| 柳林县| 芜湖市| 乌拉特前旗| 依兰县| 饶河县|