<samp id="tdkee"></samp>

    <mark id="tdkee"><acronym id="tdkee"></acronym></mark>

  1. 免费看又黄又无码的网站_久久久高清国产免费观看_亚洲一区二区三区在线免费观看_免费欧洲美女a视频一级毛片_日本最新免费二区三区

    ×

    java虛擬機(jī)類加載機(jī)制

    • 作者:新網(wǎng)
    • 來(lái)源:新網(wǎng)
    • 瀏覽:100
    • 2018-05-02 17:54:06

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

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

    <div>  與編譯時(shí)需要連接的語(yǔ)言不同,Java語(yǔ)言類加載、連接和初始化都是在程序執(zhí)行期間完成的,增加了性能開(kāi)銷但提高了就Java程序的靈活性,Java里天生可以動(dòng)態(tài)擴(kuò)展的語(yǔ)言特性就依賴運(yùn)行期動(dòng)態(tài)加載和動(dòng)態(tài)鏈接這個(gè)特點(diǎn)完成的。
    t018d18e21ebcabe958.jpg
     
      2.類加載的時(shí)機(jī)
      (1)類從加載到虛擬機(jī)內(nèi)存,到卸載出內(nèi)存,整個(gè)生命周期:加載、驗(yàn)證、準(zhǔn)備、解析、初始化、使用、卸載。其中驗(yàn)證、準(zhǔn)備、解析統(tǒng)稱連接。
      (2)加載、驗(yàn)證、準(zhǔn)備、初始化、卸載這5個(gè)階段順序是確定的(開(kāi)始時(shí)間順序一定,進(jìn)行或完成通常是交叉的),解析可能在初始化后再開(kāi)始,這是為了支持Java語(yǔ)言的運(yùn)行時(shí)綁定。
      (3)加載的時(shí)機(jī)沒(méi)有強(qiáng)制約束,初始化卻有,下面5種情況必須進(jìn)行立即對(duì)類的初始化(有且只有這5種)
      1.使用new實(shí)例化對(duì)象、讀取或設(shè)置、一個(gè)類的靜態(tài)字段(final修飾,編譯期把結(jié)果放入常量池的靜態(tài)字段除外),調(diào)用一個(gè)類的靜態(tài)方法;
      2.使用Java.lang.reflect包的方法對(duì)類進(jìn)行反射調(diào)用;
      3.當(dāng)初始化一個(gè)類時(shí),該類的父類沒(méi)有進(jìn)行初始化,就觸發(fā)父類初始化;
      4.當(dāng)虛擬機(jī)啟動(dòng)時(shí),用戶包含main()方法的類,虛擬機(jī)會(huì)先初始化該類;
      5.當(dāng)使用JDK 1.7的動(dòng)態(tài)語(yǔ)言支持時(shí)。
      (4)上面5中情況稱為對(duì)一個(gè)類主動(dòng)引用,除此之外都是被動(dòng)引用
      被動(dòng)引用3個(gè)例子:
      1.通過(guò)子類引用父類中定義的靜態(tài)字段,只會(huì)觸發(fā)父類初始化;
      2.new一個(gè)類的數(shù)組,并不會(huì)觸發(fā)該類初始化,而是初始化一個(gè)由虛擬機(jī)自動(dòng)生成,直接繼承Object的子類。該類代表數(shù)組元素類型的一維數(shù)組,實(shí)現(xiàn)了數(shù)組應(yīng)有的屬性和方法,Java語(yǔ)言對(duì)數(shù)組
      的訪問(wèn)比C/C++相對(duì)安全就是因?yàn)樵擃惙庋b了數(shù)組元素的訪問(wèn)方法。
      3.一個(gè)類的靜態(tài)字段(final修飾,編譯期把結(jié)果放入常量池的靜態(tài)字段)不會(huì)被初始化
      (5)一個(gè)接口初始化時(shí)并不要求其父接口全部完成初始化,只有在真正使用到父接口的時(shí)候(如引用接口中定義的常量)才會(huì)初始化。
      3.類加載的過(guò)程
      (1)加載
      虛擬機(jī)完成3件事
      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.生成一個(gè)代表該類的java.lang.Class對(duì)象,作為方法區(qū)這個(gè)類的各種數(shù)據(jù)訪問(wèn)入口
      加載階段是開(kāi)發(fā)人員可控性最強(qiáng)時(shí)期,可以使用用戶自定義類加載器完成;數(shù)組類本身不能通過(guò)類加載器創(chuàng)建,它是由Java虛擬機(jī)直接創(chuàng)建,但數(shù)組類的元素類型最終還是靠類加載器創(chuàng)建。
      加載階段完成后,虛擬機(jī)外部的二進(jìn)制字節(jié)流就按照虛擬機(jī)所需的格式存儲(chǔ)在方法區(qū)之中,然后在內(nèi)存中實(shí)例化一個(gè)java.lang.Class對(duì)象,并不一定在堆中,HotSpot虛擬機(jī)將其存放在方法區(qū)。
      加載階段與連接階段的部分內(nèi)容是交叉進(jìn)行的,加載階段尚未完成,連接階段可能已開(kāi)始。
      (2)驗(yàn)證
      確保Class文件的字節(jié)流中包含的信息符合當(dāng)前虛擬機(jī)的要求。Java語(yǔ)言是相對(duì)安全的語(yǔ)言,使用純粹的Java代碼無(wú)法做到諸如訪問(wèn)數(shù)組邊界以外的數(shù)據(jù),將一個(gè)對(duì)象轉(zhuǎn)型為它并未實(shí)現(xiàn)的類型等等。如果這樣做編譯器就會(huì)拒絕編譯,但Class文件并不一定要求是就Java源碼編譯而來(lái),可以是從其他jvm上的語(yǔ)言來(lái)或者用十六進(jìn)制編輯器直接編寫產(chǎn)生Class文件。在字節(jié)碼層面上很多Java代碼無(wú)法做到的事情是可以實(shí)現(xiàn)的,所以需要檢查輸入的字節(jié)流,驗(yàn)證就是虛擬機(jī)對(duì)自身進(jìn)行保護(hù)的工作。
      驗(yàn)證過(guò)程大致完成下面4個(gè)階段的檢驗(yàn)動(dòng)作:
      1.文件格式驗(yàn)證:
      驗(yàn)證字節(jié)流是否符合Class文件格式的規(guī)范,并且能被當(dāng)前版本的虛擬機(jī)處理,比如:是否以魔數(shù)0xCAFEBABE開(kāi)頭、主次版本號(hào)是否在當(dāng)前虛擬機(jī)處理范圍、常量池中是否有不被支持的常量
      類型等等。 只有通過(guò)這個(gè)階段的驗(yàn)證后,字節(jié)流才會(huì)進(jìn)入內(nèi)存的方法區(qū)進(jìn)行存儲(chǔ),所有后面3個(gè)階段全部是基于方法區(qū)存儲(chǔ)結(jié)構(gòu)進(jìn)行的,不會(huì)直接操作字節(jié)流。
      2.元數(shù)據(jù)驗(yàn)證:
      對(duì)字節(jié)碼描述的信息進(jìn)行語(yǔ)義分析,以保證其描述的信息符合Java語(yǔ)言規(guī)范,比如:是否有父類(除了java.lang.Object之外所有類要有父類)、是的繼承了不該繼承的類(final)、如果不是抽
      象類是否實(shí)現(xiàn)了其父類或接口中的所有要實(shí)現(xiàn)的方法。
      3.字節(jié)碼原則:
      主要目的通過(guò)數(shù)據(jù)流和控制流分析,確定程序語(yǔ)義是合法、符合邏輯的。在第二階段對(duì)元信息中的數(shù)據(jù)類型做完校驗(yàn)后,這個(gè)階段將對(duì)類的方法體進(jìn)行校驗(yàn)分析,保證被校驗(yàn)類的方法在運(yùn)行時(shí)
      不會(huì)做出危害虛擬機(jī)安全的事件。比如:保證任意時(shí)刻操作數(shù)棧的數(shù)據(jù)類型與指令代碼序列都能配合工作、保證跳轉(zhuǎn)指令不會(huì)跳轉(zhuǎn)到方法體以外的字節(jié)碼等等。
      4.符號(hào)引用驗(yàn)證:
      這一階段發(fā)生在虛擬機(jī)將符號(hào)引用轉(zhuǎn)化為直接引用的時(shí)候,也就是在解析階段發(fā)生。通常需要校驗(yàn)的內(nèi)容有:符號(hào)引用中通過(guò)字符串描述的全限定名是否能找到對(duì)應(yīng)的類、符號(hào)引用中類的訪問(wèn)
      性是否能被當(dāng)前類訪問(wèn)。
      (3)準(zhǔn)備
      準(zhǔn)備階段是正式為類變量分配內(nèi)存并設(shè)置類變量初始化值,這些變量使用的內(nèi)存都將在方法區(qū)中分配,初始化值為零值。注意該階段進(jìn)行內(nèi)存分配的僅包括類變量(static),不包括實(shí)例變量,實(shí)例變量將在對(duì)象實(shí)例化時(shí)隨對(duì)象一起分配在堆中。
      (4)解析,將虛擬機(jī)將常量池內(nèi)的符號(hào)引用替換為直接引用的過(guò)程
      (5)初始化,初始化階段真正開(kāi)始執(zhí)行類中定義的Java程序代碼,對(duì)類變量初始化用戶定義的值
      4.類加載器
      (1)執(zhí)行通過(guò)一個(gè)類的全限定名獲取描述此類的二進(jìn)制流,該動(dòng)作放在Java虛擬機(jī)外部實(shí)現(xiàn)
      (2)對(duì)于任意一個(gè)類,都需要由加載它的類加載期和這個(gè)類本身一同確定其在Java虛擬機(jī)中的唯一性,每個(gè)類加載器都有一個(gè)獨(dú)立的類名稱空間。
      (3)比較兩個(gè)類是否相等:Class對(duì)象equals()方法、isAssignableFrom()、isInstance()的返回結(jié)果,只有在兩個(gè)類由同一個(gè)類加載器加載的前提下才有意義。
      (5)類加載器類型:
      1.從Java虛擬機(jī)的角度來(lái)講,只存在兩種兩種不同的類加載器:?jiǎn)?dòng)類加載器,虛擬機(jī)自身的一部分;其他類加載器,獨(dú)立于虛擬機(jī)外部。
      2.從開(kāi)發(fā)人員角度:
      啟動(dòng)類加載器:負(fù)責(zé)將JAVA_HOME/lib目錄中的,或者被-Xbootclasspath參數(shù)指定的路徑中的,并能被虛擬機(jī)識(shí)別的類庫(kù)加載到內(nèi)存,啟動(dòng)類加載器無(wú)法被Java程序無(wú)法直接引用。
      擴(kuò)展類加載器:負(fù)責(zé)加載JAVA_HOME/lib/ext目錄中,或者被java.ext.dirs系統(tǒng)變量指定的路徑中的所有類庫(kù),開(kāi)發(fā)人員可直接使用。
      應(yīng)用程序類加載器(系統(tǒng)類加載器):負(fù)責(zé)用戶類路徑(classpath)上指定的類庫(kù),可直接使用,如果應(yīng)用程序沒(méi)有自定義過(guò)自己的類加載器一般就用程序默認(rèn)的類加載器。
      (6)雙親委派模型
      該模型要求除了頂層的啟動(dòng)類加載器,其余的類加載器都應(yīng)當(dāng)有自己的父類加載器,父子關(guān)系不是通過(guò)繼承的關(guān)系來(lái)實(shí)現(xiàn),而是通過(guò)組合關(guān)系來(lái)復(fù)用父加載器。
      過(guò)程:如果一個(gè)類加載器收到類加載的請(qǐng)求,他首先不會(huì)自己去嘗試,而是委派父類加載器去完成,每一層都是如此,因此所有的加載請(qǐng)求都會(huì)傳到頂層的啟動(dòng)類加載器,只有當(dāng)父加載器反饋?zhàn)约簾o(wú)法加載時(shí),子加載器才嘗試自己加載。
      好處:Java類隨它的類加載器而具有一種優(yōu)先級(jí)的層次關(guān)系。比如java.lang.Object無(wú)論誰(shuí)去加載它都會(huì)是同一個(gè)類(不同類加載器有其獨(dú)立的類名稱空間,只有在兩個(gè)類由同一個(gè)類加載器加載的前提下才有意義),如果各自加載又會(huì)有多個(gè)Object類,Java類型體系中最基礎(chǔ)的行為也就無(wú)法保證。
      (7)破壞雙親委派模型
      Java不提倡用戶再去覆蓋loadClass()方法,而是把自己的類加載邏輯寫入findClass()方法中,loadClass()邏輯是如果父加載器加載失敗,就調(diào)用自己的findClass()方法來(lái)完成加載。
    以上就是虛擬機(jī)的加載機(jī)制。

    免責(zé)聲明:本文內(nèi)容由互聯(lián)網(wǎng)用戶自發(fā)貢獻(xiàn)自行上傳,本網(wǎng)站不擁有所有權(quán),也不承認(rèn)相關(guān)法律責(zé)任。如果您發(fā)現(xiàn)本社區(qū)中有涉嫌抄襲的內(nèi)容,請(qǐng)發(fā)送郵件至:operations@xinnet.com進(jìn)行舉報(bào),并提供相關(guān)證據(jù),一經(jīng)查實(shí),本站將立刻刪除涉嫌侵權(quán)內(nèi)容。

    免費(fèi)咨詢獲取折扣

    Loading
    国产精品视频白浆免费视频_久久久高清国产免费观看_亚洲一区二区三区在线免费观看_免费欧洲美女a视频一级毛片

    <samp id="tdkee"></samp>

      <mark id="tdkee"><acronym id="tdkee"></acronym></mark>