




版權(quán)說(shuō)明:本文檔由用戶提供并上傳,收益歸屬內(nèi)容提供方,若內(nèi)容存在侵權(quán),請(qǐng)進(jìn)行舉報(bào)或認(rèn)領(lǐng)
文檔簡(jiǎn)介
1、首先聲明,我是因?yàn)榭戳薎mport HYPERLINK /channel/w/new New網(wǎng)站上的幾篇關(guān)于類 HYPERLINK /channel/w/%E5%8A%A0%E8%BD%BD%E5%99%A8 加載器的文章之后,才萌生了寫(xiě)這篇文章的想法。所以在寫(xiě)這篇文章時(shí),參考了該網(wǎng)站上的幾篇相關(guān)的文章,但是加入了很多自己的理解,絕對(duì)不是抄襲。從 HYPERLINK /channel/w/java java的動(dòng)態(tài)性到類加載機(jī)制我們知道,Java是一種動(dòng)態(tài)語(yǔ)言。那么怎樣理解這個(gè)“動(dòng)態(tài)”呢?或者說(shuō)一門(mén)語(yǔ)言具備了什么特性,才能稱之為動(dòng)態(tài)語(yǔ)言呢?對(duì)于java,我是這樣理解的。我們都知道JVM( HYP
2、ERLINK /channel/w/java%E8%99%9A%E6%8B%9F%E6%9C%BA java虛擬機(jī))執(zhí)行的不是本地機(jī)器碼指令,而是執(zhí)行一種稱之為字節(jié)碼的指令(存在于cl HYPERLINK /channel/w/ass ass文件中)。這就要求 HYPERLINK /channel/w/%E8%99%9A%E6%8B%9F%E6%9C%BA 虛擬機(jī)在真正執(zhí)行字節(jié)碼之前,先把相關(guān)的class文件加載到 HYPERLINK /channel/w/%E5%86%85%E5%AD%98 內(nèi)存中。虛擬機(jī)不是一次性加載所有需要的class文件,因?yàn)樗趫?zhí)行的時(shí)候根本不會(huì)知道以后會(huì)用到哪些c
3、lass文件。它是每用到一個(gè)類,就會(huì)在運(yùn)行時(shí)“動(dòng)態(tài)地”加載和這個(gè)類相關(guān)的class文件。這就是java被稱之為動(dòng)態(tài)性語(yǔ)言的根本原因。除了動(dòng)態(tài)加載類之外,還會(huì)動(dòng)態(tài)的初始化類,對(duì)類進(jìn)行動(dòng)態(tài)鏈接。動(dòng)態(tài)初始化和動(dòng)態(tài)鏈接放在其他文章中進(jìn)行介紹。本文中只關(guān)心類的加載。在JVM中負(fù)責(zé)對(duì)類進(jìn)行加載的正是本文要介紹的類加載器( HYPERLINK /channel/w/classloader ClassLoader),所以,類加載器是JVM不可或缺的重要組件。java中的類加載器及類加載器工作原理java中(指的是javase)有三種類加載器。每個(gè)類加載器在創(chuàng)建的時(shí)候已經(jīng)指定他們對(duì)應(yīng)的目錄,也就是說(shuō)每個(gè)類加載器
4、去哪里加載類是確定的,我認(rèn)為在ClassLoader類中應(yīng)該會(huì)有g(shù)etTargetPath之類的方法,得到他們對(duì)應(yīng)的路徑,找了找 HYPERLINK /channel/w/jdk jdk的文檔,發(fā)現(xiàn)是沒(méi)有的。以下是這三種類加載器和他們對(duì)應(yīng)的路徑:* AppClassLoader -加載classpath指定的路徑中的類* HYPERLINK /channel/w/extclassloader ExtClassLoader-加載 HYPERLINK /channel/w/jre jre/ HYPERLINK /channel/w/lib lib/ HYPERLINK /channel/w/ext
5、 ext目錄下或者java.ext.dirs系統(tǒng)屬性定義的目錄下的類* HYPERLINK /channel/w/bootstrap BootStrap-加載JRE/lib/rt.jar中的類那么類加載器是如何工作的呢?可以參看jdk中ClassLoader類的源碼。這個(gè)類的實(shí)現(xiàn)使用了模板方法模式,首先是loadClass方法來(lái)加載類,loadClass方法又調(diào)用了findClass方法,該方法讀取并返回類文件的數(shù)據(jù),findClass方法返回后,loadClass方法繼續(xù)調(diào)用defineClass方法,將返回的數(shù)據(jù)加工成虛擬機(jī)運(yùn)行時(shí)可識(shí)別的類型信息。所以,我們?nèi)绻_(kāi)發(fā)自己的類加載器,只需要繼
6、承jdk中的ClassLoader類,并覆蓋findClass方法就可以了,剩下的而工作,父類會(huì)完成。其他java平臺(tái)有的根據(jù)自己的需求,實(shí)現(xiàn)了自己特定的類加載器,例如 HYPERLINK /channel/w/javaee javaee平臺(tái)中的tomcat HYPERLINK /channel/w/%E6%9C%8D%E5%8A%A1%E5%99%A8 服務(wù)器, HYPERLINK /channel/w/android%E5%B9%B3%E5%8F%B0 Android平臺(tái)中的dalvik虛擬機(jī)也定義了自己的類加載器。虛擬機(jī)加載類有兩種方式,一種方式就是上面提到的ClassLoader.lo
7、adClass方法,另一種是使用反射API,Class.forName方法,其實(shí)Class.forName方法內(nèi)部也是使用的ClassLoader。Class類中forName方法的實(shí)現(xiàn)如下:javaview plaincopypublicstaticClass forName(String name,boolean HYPERLINK /channel/w/initialize initialize,ClassLoader HYPERLINK /channel/w/loader loader)throws HYPERLINK /channel/w/classnotfoundexception
8、 ClassNotFoundExceptionif(loader =null) SecurityManager sm = System.getSecurityManager;if(sm !=null) ClassLoader ccl = ClassLoader.getCallerClassLoader;if(ccl !=null) sm.checkPermission(SecurityConstants.GET_CLASSLOADER_PERMISSION);returnforName0(name, initialize, loader);/* Called after security ch
9、ecks have been made. */privatestaticnativeClass forName0(String name,boolean HYPERLINK /channel/w/initialize initialize,ClassLoader loader)throwsClassNotFoundException;類加載器的三個(gè)特性類加載器有三個(gè)特性,分別為委派,可見(jiàn)性和單一性,其他文章上對(duì)這三個(gè)特性的介紹如下:*委托機(jī)制是指將加載一個(gè)類的請(qǐng)求交給父類加載器,如果這個(gè)父類加載器不能夠找到或者加載這個(gè)類,那么再加載它。*可見(jiàn)性的原理是子類的加載器可以看見(jiàn)所有的父類加載器加載的
10、類,而父類加載器看不到子類加載器加載的類。*單一性原理是指僅加載一個(gè)類一次,這是由委托機(jī)制確保子類加載器不會(huì)再次加載父類加載器加載過(guò)的類。其中,委派機(jī)制是基礎(chǔ),在其他資料中也把這種機(jī)制叫做類加載器的雙親委派模型,其實(shí)說(shuō)的是同一個(gè)意思。可加性和單一性是依賴于委派機(jī)制的。以下代碼測(cè)試類加載器的委派機(jī)制:javaview plaincopyClassLoader appClassLoader = ClassLoaderTest.class.getClassLoader;System.out.println(appClassLoader);/sun.misc.Launcher$AppClassLoad
11、er19821fClassLoader extClassLoader = appClassLoader.getParent;System.out.println(extClassLoader);/sun.misc.Launcher$ExtClassLoaderaddbf1/AppClassLoader的父加載器是ExtClassLoaderSystem.out.println(extClassLoader.getParent);/null/ExtClassLoader的父加載器是null,也就是BootStrap,這是由c語(yǔ)言實(shí)現(xiàn)的由打印結(jié)果可知,加載我們自己編寫(xiě)的類的加載器是AppClass
12、Loader,AppClassLoader的父加載器是ExtClassLoader,在而ExtClassLoader的父加載器返回結(jié)果為null,這說(shuō)明他的附加載器是BootStrap,這個(gè)加載器是和虛擬機(jī)緊密聯(lián)系在一起的,在虛擬機(jī)啟動(dòng)時(shí),就會(huì)加載jdk中的類。它是由C實(shí)現(xiàn)的,沒(méi)有對(duì)應(yīng)的java對(duì)象,所以返回null。但是在邏輯上,BootStrap仍是ExtClassLoader的父加載器。也就是說(shuō)每當(dāng)ExtClassLoader加載一個(gè)類時(shí),總會(huì)委托給BootStrap加載。系統(tǒng)類加載器和線程上下文類加載器在java中,還存在兩個(gè)概念,分別是系統(tǒng)類加載器和線程上下文類加載器。其實(shí)系統(tǒng)類加載
13、器就是AppClassLoader應(yīng)用程序類加載器,它兩個(gè)值得是同一個(gè)加載器,以下代碼可以驗(yàn)證:javaview plaincopyClassLoader appClassLoader = ClassLoaderTest.class.getClassLoader;System.out.println(appClassLoader);/sun.misc.Launcher$AppClassLoader19821fClassLoader sysClassLoader = ClassLoader.getSystemClassLoader;System.out.println(sysClassLoade
14、r);/sun.misc.Launcher$AppClassLoader19821f/由上面的驗(yàn)證可知,應(yīng)用程序類加載器和系統(tǒng)類加載器是相同的,因?yàn)榈刂肥且粯拥倪@兩個(gè)類加載器對(duì)應(yīng)的輸出,不僅類名相同,連對(duì)象的 HYPERLINK /channel/w/%E5%93%88%E5%B8%8C%E5%80%BC 哈希值都是一樣的,這充分說(shuō)明系統(tǒng)類加載器和應(yīng)用程序類加載器不僅是同一個(gè)類,更是同一個(gè)類的同一個(gè)對(duì)象。每個(gè)線程都會(huì)有一個(gè)上下文類加載器,由于在線程執(zhí)行時(shí)加載用到的類,默認(rèn)情況下是父線程的上下文類加載器,也就是AppClassLoader。javaview plaincopynew HYPERL
15、INK /channel/w/thread Thread(newRunnable Overridepublicvoidrun ClassLoader threadcontextClassLosder = Thread.currentThread.getContextClassLoader;System.out.println(threadcontextClassLosder);/sun.misc.Launcher$AppClassLoader19821f).start;這個(gè)子線程在執(zhí)行時(shí)打印的信息為sun.misc.Launcher$AppClassLoader19821f,可以看到和主線程中
16、的AppClassLoader是同一個(gè)對(duì)象( HYPERLINK /channel/w/%E5%93%88%E5%B8%8C%E5%80%BC 哈希值相同)。也可以為線程設(shè)置特定的類加載器,這樣的話,線程在執(zhí)行時(shí)就會(huì)使用這個(gè)特定的類加載器來(lái)加載使用到的類。如下代碼:javaview plaincopyThread th =newThread(newRunnable Overridepublicvoidrun ClassLoader threadcontextClassLosder = Thread.currentThread.getContextClassLoader;System.out.p
17、rintln(threadcontextClassLosder);/jg.zhang.java.testclassloader.ClassLoaderTest$31b67f74);th.setContextClassLoader(newClassLoader );th.start;在線程運(yùn)行之前,為它設(shè)置了一個(gè)匿名內(nèi)部類的類加載器對(duì)象,線程運(yùn)行時(shí),輸出的信息為:jg.zhang.java.testclassloader.ClassLoaderTest$31b67f74,也就是我們?cè)O(shè)置的那個(gè)類加載器對(duì)象。類加載器的可見(jiàn)性下面驗(yàn)證類加載器的可見(jiàn)性,也就是子類的加載器可以看見(jiàn)所有的父類加載器加載的類
18、,而父類加載器看不到子類加載器加載的類。以下代碼使用父加載器ExtClassLoader加載子加載器AppClassLoader路徑下的類,由輸出可知,是不可能實(shí)現(xiàn)的。javaview plaincopytryClass.forName(jg.zhang.java.testConcurrent.Person,true,ClassLoaderTest.class.getClassLoader.getParent);System.out.println(1 -類被加載);catch(ClassNotFoundException e) /e.printStackTrace;System.out.pr
19、intln(1 -未找到類);輸出為 :1 -未找到類 。說(shuō)明拋出了ClassNotFoundException異常。原因是讓ExtClassLoader加載 jg.zhang.java.testConcurrent.Person這個(gè)類因?yàn)檫@個(gè)類不在jre/lib/ext目錄下或者java.ext.dirs系統(tǒng)屬性定義的目錄下,所以拋出ClassNotFoundException。所以父加載器不能加載應(yīng)該被子加載器加載的類。也就是說(shuō)這個(gè)類在父加載器中不可見(jiàn)。這種機(jī)制依賴于委派機(jī)制。下面代碼使用子加載器AppClassLoader加載父加載器BootStrap中的類,這是可以實(shí)現(xiàn)的。javavi
20、ew plaincopytryClass.forName(java.lang.String,true,ClassLoaderTest.class.getClassLoader);System.out.println(2 -類被加載);catch(ClassNotFoundException e) /e.printStackTrace;System.out.println(2 -未找到類);輸出為:2 -類被加載。說(shuō)明成功加載了String類。是因?yàn)樵谥付ㄓ葾ppClassLoader加載String類時(shí),由AppClassLoader一直委派到BootStrap加載。雖然是由子加載器的父加載器
21、加載的,但是也可以說(shuō),父加載器加載的類對(duì)于子加載器來(lái)說(shuō)是可見(jiàn)的。這同樣依賴于委派機(jī)制。其實(shí)在虛擬機(jī)啟動(dòng)初期,java.lang.String已經(jīng)被BootStrap預(yù)加載了,這時(shí)再次加載,虛擬機(jī)發(fā)現(xiàn)已經(jīng)加載,不會(huì)再重復(fù)加載。這同時(shí)也證明了類加載器的單一性。測(cè)試代碼到此為止,類加載器的知識(shí)就全部講完了。以下是整個(gè)測(cè)試代碼:javaview plaincopypackagejg.zhang.java.testclassloader;/*參考ImportNew上的一篇文章,*文章地址:/6581.html* Java類加載器基于三個(gè)機(jī)制:委托、可見(jiàn)性和單一性。*委托機(jī)制是指將加載一個(gè)類的請(qǐng)求交給父類
22、加載器,如果這個(gè)父類加載器不能夠找到或者加載這個(gè)類,那么再加載它。*可見(jiàn)性的原理是子類的加載器可以看見(jiàn)所有的父類加載器加載的類,而父類加載器看不到子類加載器加載的類。*單一性原理是指僅加載一個(gè)類一次,這是由委托機(jī)制確保子類加載器不會(huì)再次加載父類加載器加載過(guò)的類。*三種類加載器:每個(gè)類加載器在創(chuàng)建的時(shí)候已經(jīng)指定他們對(duì)應(yīng)的目錄,也就是說(shuō)每個(gè)類加載器去哪里加載類是確定的*我認(rèn)為在ClassLoader類中應(yīng)該會(huì)有g(shù)etTargetPath之類的方法,得到他們對(duì)應(yīng)的路徑,找了找 HYPERLINK /channel/w/jdk jdk的文檔,發(fā)現(xiàn)是沒(méi)有的.* AppClassLoader -加載cla
23、sspath指定的路徑中的類* ExtClassLoader -加載jre/lib/ext目錄下或者java.ext.dirs系統(tǒng)屬性定義的目錄下的類* BootStrap -加載JRE/lib/rt.jar中的類* author zhangjg*/publicclassClassLoaderTest publicstaticvoidmain(String args) HYPERLINK /channel/w/test1 test1;test2;test3;/*驗(yàn)證線程上下文類加載器*/privatestaticvoidtest3 /* 1每個(gè)線程都會(huì)有一個(gè)上下文類加載器,由于在線程執(zhí)行時(shí)加載
24、用到的類,默認(rèn)情況下是父線程*的上下文類加載器,也就是AppClassLoader*/newThread(newRunnable Overridepublicvoidrun ClassLoader threadcontextClassLosder = Thread.currentThread.getContextClassLoader;System.out.println(threadcontextClassLosder);/sun.misc.Launcher$AppClassLoader19821f).start;/* 2也可以給創(chuàng)建的線程設(shè)定特定的上下文類加載器*/Thread th =n
25、ewThread(newRunnable Overridepublicvoidrun ClassLoader threadcontextClassLosder = Thread.currentThread.getContextClassLoader;System.out.println( HYPERLINK /channel/w/thread threadcontextClassLosder);/jg.zhang.java.testclass HYPERLINK /channel/w/loader loader.ClassLoaderTest$31b67f74);th.setContextCl
26、assLoader( HYPERLINK /channel/w/new newClassLoader );th.start;/*測(cè)試可見(jiàn)性,可見(jiàn)性依賴于委托機(jī)制*/privatestaticvoidtest2 /* 1讓ExtClassLoader加載 jg.zhang.java.testConcurrent.Person這個(gè)類*因?yàn)檫@個(gè)類不在 HYPERLINK /channel/w/jre jre/ HYPERLINK /channel/w/lib lib/ext目錄下或者java.ext.dirs系統(tǒng)屬性定義的目錄下*所以拋出ClassNotFoundException*所以父加載器不能
27、加載應(yīng)該被子加載器加載的類,這個(gè)類在父加載器中不可見(jiàn)*這種機(jī)制依賴于委派機(jī)制*/tryClass.forName(jg.zhang.java.testConcurrent.Person,true,ClassLoaderTest.class.getClassLoader.getParent);System.out.println(1 -類被加載);catch(ClassNotFoundException e) /e.printStackTrace;System.out.println(1 -未找到類);/* 2讓AppClassLoader加載java.lang.String類*沒(méi)有拋出異常,說(shuō)
28、明類被正常加載了*雖然是由AppClassLoader一直委派到BootStrap而加載的*所以可以說(shuō),父加載器加載的類對(duì)于子加載器來(lái)說(shuō)是可見(jiàn)的,這同樣依賴于委派機(jī)制*其實(shí)在虛擬機(jī)啟動(dòng)初期,java.lang.String已經(jīng)被BootStrap預(yù)加載了*這時(shí)再次加載, HYPERLINK /channel/w/%E8%99%9A%E6%8B%9F%E6%9C%BA 虛擬機(jī)發(fā)現(xiàn)已經(jīng)加載,不會(huì)再重復(fù)加載*/tryClass.forName( HYPERLINK /channel/w/java java.lang.String,true,ClassLoaderTest.class.getClassLoader);System.out.println(2 -類被加載);catch( HYPERLINK /channel/w/cl
溫馨提示
- 1. 本站所有資源如無(wú)特殊說(shuō)明,都需要本地電腦安裝OFFICE2007和PDF閱讀器。圖紙軟件為CAD,CAXA,PROE,UG,SolidWorks等.壓縮文件請(qǐng)下載最新的WinRAR軟件解壓。
- 2. 本站的文檔不包含任何第三方提供的附件圖紙等,如果需要附件,請(qǐng)聯(lián)系上傳者。文件的所有權(quán)益歸上傳用戶所有。
- 3. 本站RAR壓縮包中若帶圖紙,網(wǎng)頁(yè)內(nèi)容里面會(huì)有圖紙預(yù)覽,若沒(méi)有圖紙預(yù)覽就沒(méi)有圖紙。
- 4. 未經(jīng)權(quán)益所有人同意不得將文件中的內(nèi)容挪作商業(yè)或盈利用途。
- 5. 人人文庫(kù)網(wǎng)僅提供信息存儲(chǔ)空間,僅對(duì)用戶上傳內(nèi)容的表現(xiàn)方式做保護(hù)處理,對(duì)用戶上傳分享的文檔內(nèi)容本身不做任何修改或編輯,并不能對(duì)任何下載內(nèi)容負(fù)責(zé)。
- 6. 下載文件中如有侵權(quán)或不適當(dāng)內(nèi)容,請(qǐng)與我們聯(lián)系,我們立即糾正。
- 7. 本站不保證下載資源的準(zhǔn)確性、安全性和完整性, 同時(shí)也不承擔(dān)用戶因使用這些下載資源對(duì)自己和他人造成任何形式的傷害或損失。
最新文檔
- 文化公園品牌建設(shè)與文化傳播策略
- 綠色供應(yīng)鏈管理在皮革行業(yè)的實(shí)踐與探索
- 高效績(jī)效管理系統(tǒng)的建設(shè)與應(yīng)用
- 供應(yīng)鏈碳足跡的評(píng)估與協(xié)同管理機(jī)制
- 數(shù)字技術(shù)對(duì)旅游業(yè)創(chuàng)新模式的推動(dòng)
- 2025年醫(yī)療互聯(lián)網(wǎng)平臺(tái)商業(yè)模式創(chuàng)新與用戶體驗(yàn)智能化報(bào)告
- 2025年醫(yī)療AI輔助診斷產(chǎn)品注冊(cè)審批政策與市場(chǎng)分析報(bào)告
- 2025年休閑食品行業(yè)健康化轉(zhuǎn)型與市場(chǎng)拓展深度分析報(bào)告
- 2025年休閑食品健康化轉(zhuǎn)型與健康食品活動(dòng)策劃市場(chǎng)拓展的實(shí)戰(zhàn)案例報(bào)告
- 智慧城市公共服務(wù)的社會(huì)參與激勵(lì)機(jī)制研究
- 江蘇省南京市聯(lián)合體2022-2023八年級(jí)初二下學(xué)期期中英語(yǔ)試卷+答案
- 2022年江蘇蘇州獨(dú)墅湖科教創(chuàng)新區(qū)管理委員會(huì)招聘筆試備考題庫(kù)及答案解析
- 事業(yè)單位崗位職數(shù)情況表
- 糖尿病的外周血管病變和處置培訓(xùn)課件
- Ф9.52銅管表冷器計(jì)算書(shū)
- 鉆沖孔灌注樁監(jiān)理實(shí)施細(xì)則
- GB/T 21352-2022地下礦井用鋼絲繩芯阻燃輸送帶
- GM/T 0021-2012動(dòng)態(tài)口令密碼應(yīng)用技術(shù)規(guī)范
- GB/T 5211.12-2007顏料水萃取液電阻率的測(cè)定
- GB/T 28022-2021玩具適用年齡判定指南
- GA/T 851-2009人行橫道信號(hào)燈控制設(shè)置規(guī)范
評(píng)論
0/150
提交評(píng)論