国产成人精品18p,天天干成人网,无码专区狠狠躁天天躁,美女脱精光隐私扒开免费观看

JVM中ClassLoader類(lèi)加載器的深入理解

發(fā)布時(shí)間:2021-07-06 11:12 來(lái)源:腳本之家 閱讀:0 作者:殺手不太冷! 欄目: 開(kāi)發(fā)技術(shù)

JVM的體系結構圖

先來(lái)看一下JVM的體系結構,如下圖:

JVM的位置

JVM的位置,如下圖:

JVM是運行在操作系統之上的,與硬件沒(méi)有直接的交互,但是可以調用底層的硬件,用JIN(Java本地接口調用底層硬件)

JVM結構圖中的class files文件

class files文件,是保存在我們電腦本地的字節碼文件,.java文件經(jīng)過(guò)編譯之后,就會(huì )生成一個(gè).class文件,這個(gè)文件就是class files所對應的字節碼文件,如下圖:

JVM結構圖中的類(lèi)加載器ClassLoader的解釋

 類(lèi)加載器ClassLoader的作用

類(lèi)加載器只有一個(gè)作用,就是負責把我們本地的.class字節碼文件,加載到JVM中,以類(lèi)模板的形式存在于JVM中。

類(lèi)加載器加載的.class文件也是有要求的,并不是只要是后綴名為.class的文件,都可以被類(lèi)加載器加載,這個(gè).class文件的必須是.java文件經(jīng)過(guò)編譯后得到的字節碼文件,也就是指這個(gè).class文件的開(kāi)頭必須要是cafe babe字符單詞,它的內容是經(jīng)過(guò)加密后的二進(jìn)制文件,但是此二進(jìn)制使用十六進(jìn)制表示出來(lái)的,如下圖:

類(lèi)加載器ClassLoader只負責加載.class文件,但至于他是否可以運行,由JVM中的執行引擎Excution Engine決定的。

解釋?zhuān)?/strong>

Car.class是由.java文件編譯得來(lái)的.class文件,存在本地磁盤(pán)。

ClassLoader:類(lèi)加載器,負責加載并初始化 類(lèi)文件,得到真正的Class類(lèi),即模板。

Car Class:由Car.class字節碼文件,通過(guò)ClassLoader加載并且初始化得到,這個(gè)Car就是當前類(lèi)的模板,這個(gè)Car Class模板就存在方法區。

car1,car2,car3:是由Car模板經(jīng)過(guò)實(shí)例化而得,一個(gè)模板可以獲得多個(gè)實(shí)例化對象。

拿car1舉例,car1.getClass()可以得到模板Car類(lèi),Car.getClassLoader()可得到其裝載器。

類(lèi)加載器的種類(lèi)

一共有四類(lèi)。

虛擬機自帶的加載器:

啟動(dòng)類(lèi)加載器,也叫根加載器(BootStrap)。由C++編寫(xiě),程序中自帶的類(lèi),存儲在 $JAVAHOME/jre/lib/rt.jar中,如object類(lèi)等

擴展類(lèi)加載器(Extension),Java編寫(xiě),在我們看到的類(lèi)路徑中,凡是以Javax開(kāi)頭的,都是拓展包,存儲在 $JAVAHOME/jre/lib/ext/*.jar 中,為什么會(huì )有擴展包?是因為原本的java包中在功能上,不能滿(mǎn)足我們了,所以我們就在原本的java包的基礎上擴展出了一些新的功能,而形成的新的包就叫做擴展包。

應用程序類(lèi)加載器(AppClassLoader),即平時(shí)程序中自定義的類(lèi) new出來(lái)的

用戶(hù)自定義的加載器:

Java.lang.ClassLoader的子類(lèi),用戶(hù)可以定制類(lèi)的加載方式,即如果你的程序有特殊的需求,你也可以自定義你的類(lèi)加載器的加載方式 ,進(jìn)入ClassLoader的源碼,其為抽象類(lèi),因此在你定制化開(kāi)發(fā)的時(shí)候,需要你定義自己的加載器類(lèi)來(lái)繼承ClassLoader抽象類(lèi)即可,即 MyClassLoader extends ClassLoader

java類(lèi)的加載機制

首先你需要知道,當java程序需要加載一個(gè)類(lèi)的時(shí)候,會(huì )去找類(lèi)加載器,然后找類(lèi)加載器里面看是否有對應的類(lèi)模板。

Java的類(lèi)加載機制,永遠是以 根加載器->拓展類(lèi)加載器->應用程序類(lèi)加載器 這樣的一個(gè)順序進(jìn)行加載的。什么意思呢?就是如果能在BootStrapClassLoader類(lèi)加載器的路徑下找到對應的類(lèi)模板,那么就不會(huì )再去擴展類(lèi)加載器ExtensionClassLoader中找對應的類(lèi)模板,如果能在擴展類(lèi)加載器ExtensionClassLoader中找到對應的類(lèi)模板,那么就不會(huì )去應用程序類(lèi)加載器AppClassLoader中找對應的類(lèi)模板。類(lèi)加載器的父子級關(guān)系,如下圖:

從上圖可以看出根加載器BootStrapClassLoader是擴展類(lèi)加載器ExtensionClassLoader的父級,擴展類(lèi)加載器ExtensionClassLoader是應用程序加載器AppClassLoader的父級,如下圖:

被某個(gè)類(lèi)加載器加載的類(lèi),都會(huì )存放到這個(gè)類(lèi)加載器的路徑中,當程序需要加載某個(gè)類(lèi)的時(shí)候,會(huì )先去根加載器BootstrapClassLoader的路徑下,尋找是否有這個(gè)類(lèi)的模板,如果沒(méi)有則會(huì )去這個(gè)類(lèi)加載器的下一級,若有,則不會(huì )再去下一級尋找了。

利用obj.getClass().getClassLoader()方法,可以找到對應的類(lèi)模板是存放在哪個(gè)類(lèi)加載器的路徑下的,換一個(gè)說(shuō)法,可以讓你知道在加載這個(gè)類(lèi)模板所對應的類(lèi)的字節碼文件的時(shí)候,是用的哪一個(gè)類(lèi)加載器把這個(gè)類(lèi)的字節碼文件加載成類(lèi)模板的,如下圖:

那么問(wèn)題來(lái)了?為什么說(shuō)Object類(lèi)是java自帶的類(lèi)呢?java自帶的類(lèi)到底可以在哪里找到呢?java自帶的類(lèi)可以 J A V A H O M E / j r e / l i b / r t . j a r 下 找 到 。 首 先 來(lái) 看 一 下 JAVAHOME/jre/lib/rt.jar下找到。首先來(lái)看一下 JAVAHOME/jre/lib/rt.jar下找到。首先來(lái)看一下JAVAHOME,也即是java的安裝目錄,如下圖:

然后咱來(lái)看一下$JAVAHOME/jre/lib/rt.jar中的包(rt其實(shí)也即是RunTime的縮寫(xiě)),如下圖:

打開(kāi)rt.jar壓縮包,它的目錄結構,如下圖:

Object類(lèi)在java/lang包下,如下圖:

JVM中的類(lèi)加載器,根加載器BootStrap,在一開(kāi)始,就會(huì )把rt.jar壓縮包中的所有的 類(lèi)的字節碼文件都加載到JVM中,變成類(lèi)的模板,所以這些java自帶的類(lèi),對應的類(lèi)的模板,都會(huì )被存放到根加載器BootStrap的路徑下面。故當java程序中需要用到j(luò )ava中的自帶類(lèi)的時(shí)候,都會(huì )去根加載器BootStrap的路徑下去尋找類(lèi)的模板。

雙親委派機制

官方概念:當一個(gè)類(lèi)收到類(lèi)加載請求后,他不會(huì )首先去加載這個(gè)類(lèi),而是把這個(gè)請求委派給父類(lèi)去完成。每一個(gè)層次的類(lèi)加載器都是如此,因此所有的類(lèi)加載器請求都是應該傳到根加載器中的,只有當其父類(lèi)加載器自己無(wú)法完成這個(gè)請求的時(shí)候(在他的加載路徑下沒(méi)有找到所需加載的class),子類(lèi)加載器才會(huì )嘗試自己去加載。

我的理解翻譯:當java程序需要加載一個(gè)類(lèi)的時(shí)候,比如要加載java.lang.String類(lèi),會(huì )首先去根加載器類(lèi)BootstrapClassLoader的路徑下去尋找,如果在根加載器路徑下可以找到j(luò )ava.lang.String類(lèi),那么就不會(huì )再往下尋找java.lang.String類(lèi)了,因為已經(jīng)找到了;若在根加載器路徑下沒(méi)有找到j(luò )ava.lang.String類(lèi),則會(huì )去下一級擴展類(lèi)加載器ExtensionClassLoader中尋找java.lang.String類(lèi),如果在擴展類(lèi)加載器中找到了java.lang.String類(lèi),那么就不會(huì )再去下一級類(lèi)加載器中尋找了;如果沒(méi)有找到,則會(huì )去應用程序類(lèi)加載器AppClassLoader中去尋找java.lang.String類(lèi),如果仍然沒(méi)有找到會(huì )報classNotFoundException異常。

采用雙親委派機制的好處:保證了我們寫(xiě)的代碼不會(huì )污染到j(luò )ava的源代碼,因為只要java的源代碼中存在我們即將要加載的類(lèi),那么java程序在加載類(lèi)的時(shí)候就會(huì )去頂層的根加載器BootstrapClassLoader路徑下去尋找類(lèi)模板,然后把這個(gè)類(lèi)加載。你就比如假設我們自己寫(xiě)一個(gè)java.lang包,然后在這個(gè)包里面寫(xiě)一個(gè)String類(lèi),那么如果java源代碼中沒(méi)有java.lang.String這個(gè)類(lèi),java程序在用到這個(gè)類(lèi)加載的時(shí)候,會(huì )用到應用程序類(lèi)加載器AppClassLoader路徑下的java.lang.String類(lèi),但是,我們都知道java源代碼中是有java.lang.String這個(gè)類(lèi)的,也即是在根加載器BootstrapClassLoader路徑下有java.lang.String這個(gè)類(lèi),所以java程序在用到這個(gè)類(lèi)加載它的時(shí)候,會(huì )加載根加載器BootstrapClassLoader路徑下的java.lang.String類(lèi),而不會(huì )去加載應用程序類(lèi)加載器AppClassLoader下的java.lang.String類(lèi),這樣就保證了,我們在java程序的其它地方所用到的java.lang.String類(lèi)的方法是正確的,怎么個(gè)正確法呢?因為啊,假設你是加載的應用程序加載器AppClassLoader路徑里的java.lang.String類(lèi)也即是你自己寫(xiě)的String類(lèi),那么在java程序的其它地方如果使用到了源代碼java.lang.String類(lèi)里面的方法該怎么辦?這樣是不是會(huì )出錯?這其實(shí)也就是,你寫(xiě)的代碼污染了人家寫(xiě)的源代碼。

雙親委派機制的程序理解,如下圖:

沙箱安全機制

通過(guò)雙親委派機制,類(lèi)的加載永遠都是從根加載器開(kāi)始的,如果跟加載器中沒(méi)有對應的類(lèi)模板,則會(huì )去下一級類(lèi)加載器中尋找這個(gè)類(lèi)模板,如果有的話(huà)則就不會(huì )去下一級尋找了。這樣就保證你所寫(xiě)的代碼不會(huì )污染Java自帶的源代碼,保證了沙箱的安全。

為什么說(shuō)這樣不會(huì )污染java自帶的源代碼呢?因為只要java的源代碼中存在我們即將要加載的類(lèi),那么java程序在加載類(lèi)的時(shí)候就會(huì )去頂層的根加載器BootstrapClassLoader路徑下去尋找類(lèi)模板,然后把這個(gè)類(lèi)加載。你就比如假設我們自己寫(xiě)一個(gè)java.lang包,然后在這個(gè)包里面寫(xiě)一個(gè)String類(lèi),那么如果java源代碼中沒(méi)有java.lang.String這個(gè)類(lèi),java程序在用到這個(gè)類(lèi)加載的時(shí)候,會(huì )用到應用程序類(lèi)加載器AppClassLoader路徑下的java.lang.String類(lèi),但是,我們都知道java源代碼中是有java.lang.String這個(gè)類(lèi)的,也即是在根加載器BootstrapClassLoader路徑下有java.lang.String這個(gè)類(lèi),所以java程序在用到這個(gè)類(lèi)加載它的時(shí)候,會(huì )加載根加載器BootstrapClassLoader路徑下的java.lang.String類(lèi),而不會(huì )去加載應用程序類(lèi)加載器AppClassLoader下的java.lang.String類(lèi),這樣就保證了,我們在java程序的其它地方所用到的java.lang.String類(lèi)的方法是正確的,怎么個(gè)正確法呢?因為啊,假設你是加載的應用程序加載器AppClassLoader路徑里的java.lang.String類(lèi)也即是你自己寫(xiě)的String類(lèi),那么在java程序的其它地方如果使用到了源代碼java.lang.String類(lèi)里面的方法該怎么辦?這樣是不是會(huì )出錯?這其實(shí)也就是,你寫(xiě)的代碼污染了人家寫(xiě)的源代碼。

總結

到此這篇關(guān)于JVM中ClassLoader類(lèi)加載器的文章就介紹到這了,更多相關(guān)JVM中ClassLoader類(lèi)加載器內容請搜索腳本之家以前的文章或繼續瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!

免責聲明:本站發(fā)布的內容(圖片、視頻和文字)以原創(chuàng )、來(lái)自互聯(lián)網(wǎng)轉載和分享為主,文章觀(guān)點(diǎn)不代表本網(wǎng)站立場(chǎng),如果涉及侵權請聯(lián)系QQ:712375056 進(jìn)行舉報,并提供相關(guān)證據,一經(jīng)查實(shí),將立刻刪除涉嫌侵權內容。

人人妻碰人人免费| 欧美人与禽交ZOZO| 亚洲婷婷五月综合狠狠| 亚洲午夜国产精品无码老牛影视 | 精品无码成人片一区二区98| 免费大片黄在线观看|