1 類加載器與類的加載過(guò)程
類加載器子系統(tǒng)的作用:類加載子系統(tǒng)負(fù)責(zé)從文件或者網(wǎng)絡(luò)中加載class文件泵殴,class文件在文件頭有特定的文件標(biāo)識(shí)笑诅。
類的加載過(guò)程:
加載:
1)通過(guò)一個(gè)類的全限定名獲取定義此類的二進(jìn)制字節(jié)流
2)將這個(gè)字節(jié)流所表示的靜態(tài)存儲(chǔ)結(jié)構(gòu)轉(zhuǎn)化為方法區(qū)的運(yùn)行時(shí)數(shù)據(jù)結(jié)構(gòu)
3)在內(nèi)存中生成一個(gè)代表這個(gè)java.lang.Class對(duì)象,作為方法區(qū)這個(gè)類的各種數(shù)據(jù)的訪問(wèn)入口弦叶。
鏈接:
1)驗(yàn)證:目的在于確保class文件的字節(jié)流中包含信息符合當(dāng)前虛擬機(jī)要求湾蔓,保證被加載類的正確性砌梆,不會(huì)危害虛擬機(jī)的自身安全贬循。
主要包括:文件格式驗(yàn)證,元數(shù)據(jù)驗(yàn)證杖虾,字節(jié)碼驗(yàn)證,符號(hào)引用驗(yàn)證奇适。
2)準(zhǔn)備:為類變量分配內(nèi)存空間,并賦初始默認(rèn)值嚷往。這里不包括final修飾的static皮仁,因?yàn)閒inal修飾的在編譯時(shí)就會(huì)分配了,準(zhǔn)備階段會(huì)顯式初始化贷祈。虛方法表也在此階段創(chuàng)建并開(kāi)始初始化,類的變量初始值準(zhǔn)備完成后呜达,jvm會(huì)把類的方法表也初始化完畢查近。
非前向引用:靜態(tài)代碼塊可以給定義在靜態(tài)代碼塊后的靜態(tài)變量賦值,但是不能調(diào)用勋锤。
3)解析:將常量池內(nèi)的符號(hào)引用轉(zhuǎn)壞為直接引用的過(guò)程叁执。
初始化:
初始化階段就是執(zhí)行類構(gòu)造器<clinit>()的過(guò)程矮冬,此方法不需要定義胎署,是javac編輯器自動(dòng)手機(jī)所有類變量的賦值動(dòng)作和靜態(tài)代碼塊中的語(yǔ)句合并而來(lái)。<clinit>()不同于類的構(gòu)造器恢筝,如果具有父類巨坊,jvm會(huì)保證子類的<clinit>()執(zhí)行前,父類的<clinit>()已經(jīng)執(zhí)行完畢趾撵。
2 類加載器分類
jvm支持兩周類加載器侄柔,分別為引導(dǎo)類加載器(Bootstrap ClassLader,和自定義加載器(User-Definedd ClassLoader).自定義加載器不僅是指開(kāi)發(fā)人員自己定義的類加載器占调,而是將所有派生類生于抽象類ClassLoader的類加載器都劃分為自定義類加載器暂题。
常用的三個(gè)類加載器:
1)啟動(dòng)類加載器(引導(dǎo)類加載器究珊,Bootstrap ClassLoader)
這個(gè)類加載器使用C/C++語(yǔ)言實(shí)現(xiàn)薪者,嵌套在jvm內(nèi)部苦银,用于記載java核心庫(kù)(JAVA_HOME/jre/lib/rt.jar啸胧、resources.jar或sun.boot.class.path路徑下的內(nèi)容),用于提供jvm自身需要的類幔虏。
并不繼承java.lang.ClassLoader,沒(méi)有父加載器。
出于安全考慮想括,Bootstrap啟動(dòng)類加載器只加載包名為java陷谱、javax、sun等開(kāi)頭的類。
2)擴(kuò)展類加載器(Extension ClassLoader)
由java語(yǔ)言編寫(xiě)烟逊,派生自ClassLoader類,父類加載器為啟動(dòng)類加載器宪躯。從java.ext.dirs系統(tǒng)屬性所指定的目錄中加載類庫(kù)乔宿,或從jdk安裝目錄的jre/lib/ext子目錄(擴(kuò)展目錄)下安裝類庫(kù)详瑞。如果用戶創(chuàng)建的jar在此目錄下坝橡,也會(huì)自動(dòng)由擴(kuò)展類加載器加載计寇。
3)應(yīng)用程序類加載器(AppClassLoader)
java語(yǔ)言編寫(xiě),派生于ClassLoader類番宁,父類加載器為擴(kuò)展類加載器贝淤,負(fù)責(zé)加載環(huán)境變量classpath或系統(tǒng)屬性java.class.path指定下的類庫(kù)柒竞。此類加載器是程序中默認(rèn)的加載器政供,一般來(lái)說(shuō),java應(yīng)用的類都是由它來(lái)完成的朽基。
3 ClassLoader的使用說(shuō)明
ClassLoader類是一個(gè)抽象類布隔,除了引導(dǎo)類加載器外斗繼承自ClassLoader。
sun.mis.Laucher是一個(gè)虛擬機(jī)的入口應(yīng)用稼虎,擴(kuò)展類加載器和應(yīng)用程序類加載器都是都是其定義的內(nèi)部類衅檀。
獲取ClassLoaderd的途徑:
如果是String等java核心類庫(kù),由引導(dǎo)類加載器加載霎俩,因?yàn)槭怯蒫/c++編寫(xiě)哀军,所以獲取不到相應(yīng)的對(duì)象,獲取為null打却。
1)獲取當(dāng)前類的classloader :clazz.getClassLoader()
2)獲取當(dāng)前線程上下文的ClassLoader:Thread.currentThread().getContextClassLoader()
3)獲取系統(tǒng)的ClassLoader:CladdLoader.getSystemClassLoader()
4)獲取調(diào)用者的ClassLoaderL:DriverManager.getCallerClassLoader()
4 雙親委派機(jī)制
工作原理:如果一個(gè)類加載器收到了類加載請(qǐng)求杉适,它并不會(huì)自己先去加載,而是把這個(gè)請(qǐng)求委托給父類加載器去執(zhí)行柳击,直到向上委托至最頂層的啟動(dòng)類加載器猿推。如果父類能夠完成類加載任務(wù),就成功返回,如果不能蹬叭,子加載器才會(huì)嘗試自己去加載藕咏。
優(yōu)勢(shì):避免類的重復(fù)加載。保護(hù)程序安全秽五,防止API被隨意篡改孽查。
沙箱安全機(jī)制:
自定義String類,但是在加載自定義String類的時(shí)候會(huì)率先使用引導(dǎo)類加載器加載坦喘,而引導(dǎo)類加載器在加載的過(guò)程中會(huì)先加載jdk自帶的文件卦碾,報(bào)錯(cuò)信息說(shuō)沒(méi)有main方法就是因?yàn)榧虞d的是rt.jar中的string類。這樣可以保證對(duì)java核心源代碼的保護(hù)起宽,這就是沙箱安全機(jī)制洲胖。
其他:
1)在jvm中表示兩個(gè)class對(duì)象是否為同一個(gè)類存在的兩個(gè)必要條件:類加載的完整類名必須一致,包括包名坯沪,加載這個(gè)類的列加載器必須相同绿映。
2)jvm必須知道一個(gè)類型是由啟動(dòng)類加載器還是由用戶類加載器加載的。如果一個(gè)類型是由用戶類加載器加載的腐晾,那么jvm會(huì)將這個(gè)類加載器的一個(gè)引用作為類型信息的一部分保存在方法去中叉弦,當(dāng)解析一個(gè)類型到另外一個(gè)類型的引用的時(shí)候,jvm需要保證這兩個(gè)類的類記載器是相同的藻糖。
3)類的被動(dòng)使用不會(huì)導(dǎo)致類的初始化