日韩性视频-久久久蜜桃-www中文字幕-在线中文字幕av-亚洲欧美一区二区三区四区-撸久久-香蕉视频一区-久久无码精品丰满人妻-国产高潮av-激情福利社-日韩av网址大全-国产精品久久999-日本五十路在线-性欧美在线-久久99精品波多结衣一区-男女午夜免费视频-黑人极品ⅴideos精品欧美棵-人人妻人人澡人人爽精品欧美一区-日韩一区在线看-欧美a级在线免费观看

歡迎訪問 生活随笔!

生活随笔

當前位置: 首頁 > 编程语言 > java >内容正文

java

java 类加载 双亲委派_Java类加载器和双亲委派机制

發(fā)布時間:2024/8/23 java 36 豆豆
生活随笔 收集整理的這篇文章主要介紹了 java 类加载 双亲委派_Java类加载器和双亲委派机制 小編覺得挺不錯的,現(xiàn)在分享給大家,幫大家做個參考.

前言

之前詳細介紹了Java類的整個加載過程(類加載機制詳解)。雖然,篇幅較長,但是也不要被內(nèi)容嚇到了,其實每個階段都可以用一句話來概括。

1)加載:查找并加載類的二進制字節(jié)流數(shù)據(jù)。

2)驗證:保證被加載的類的正確性。

3)準備:為類的靜態(tài)變量分配內(nèi)存,并設(shè)置默認初始值。

4)解析:把類中的符號引用轉(zhuǎn)換為直接引用。

5)初始化:為類的靜態(tài)變量賦予正確的初始值。

當然,要想掌握類加載機制,還是需要去深入研究的。(好吧,說了一句正確的廢話)因為其中,有很多知識點也是面試中常問的。比如,我之前去面試的時候,面試官就問到了一個和類初始化相關(guān)的問題。就是給一段代碼,有父子類關(guān)系,父子類中包含靜態(tài)代碼塊、構(gòu)造代碼塊、普通代碼塊、構(gòu)造函數(shù)等,然后讓判斷代碼最終的執(zhí)行順序。(可自行思考一下,具體內(nèi)容細節(jié)暫時不做擴展)

類加載器

終于來到了本文的主題 —— 類加載器和雙親委派機制。

在《深入理解Java虛擬機》中,對于類加載器的定義是這樣的:

虛擬機設(shè)計團隊把類加載階段中的“通過一個類的權(quán)限定名來獲取描述此類的二進制字節(jié)流”這個動作放到Java虛擬機外部去實現(xiàn),以便讓應(yīng)用程序自己決定如何去獲取所需要的類。實現(xiàn)這個動作的代碼模塊稱為“類加載器”。

簡單來說,類加載器的作用就是去加載class類的二進制字節(jié)流的。

類加載器有以下三種:

1)啟動類加載器(Bootstrap ClassLoader),或者叫根加載器。這個類加載器主要是去加載你在本機配置的環(huán)境變量 Java_Home/jre/lib 目錄下的核心API,如rt.jar

2)擴展類加載器(Extension ClassLoader)。這個加載器負責加載 Java_Home/jre/lib/ext 目錄下的所有jar包。

3)應(yīng)用程序類加載器(Application ClassLoader)。這個加載器加載的是你的項目工程的ClassPath目錄下的類庫。如果用戶沒有自定義自己的類加載器,這個就是程序默認的類加載器。

另外,如果有需要的話,用戶也可以自定義自己的類加載器(去繼承ClassLoader類)。

我們也可以通過代碼把類加載器打印出來:

public class TestClassLoader {

public static void main(String[] args) {

Object obj = new Object();

System.out.println(obj.getClass().getClassLoader());

TestClassLoader t = new TestClassLoader();

System.out.println(t.getClass().getClassLoader());

System.out.println(t.getClass().getClassLoader().getParent());

System.out.println(t.getClass().getClassLoader().getParent().getParent());

}

}

打印結(jié)果:

null

sun.misc.Launcher$AppClassLoader@58644d46

sun.misc.Launcher$ExtClassLoader@6d6f6e28

null

注意,上面第一行和第四行的null此處可不是空的意思,它代表的是啟動類加載器。因為啟動類加載器是用C++代碼來實現(xiàn)的,嚴格來說不屬于Java類,所以Java代碼訪問不到,故返回null。第二行是應(yīng)用程序類加載器,第三行是擴展類加載器。

雙親委派機制

在介紹雙親委派機制之前,先觀察一下以下代碼能否正確運行:

//自己定義的一個 java.lang包

package java.lang;

public class String {

public static void main(String[] args) {

String s = new String();

System.out.println(s);

}

}

以上代碼,編譯沒有任何問題,但是運行時,卻報錯:

為什么提示在java.lang.String類中找不到main方法呢,我這明明不是定義了嗎?其實,問題的關(guān)鍵就在于類加載遵循雙親委派機制。

類加載器有以下這樣的層次關(guān)系:

當一個類在加載的時候,都會先委派它的父加載器去加載,這樣一層層的向上委派,直到最頂層的啟動類加載器。如果頂層無法加載(即找不到對應(yīng)的類),就會一層層的向下查找,直到找到為止。 這就是類的雙親委派機制。

這樣做有什么好處呢?這就相當于維護了一個有優(yōu)先級的層級關(guān)系,即總是從最頂層的父加載器開始加載。這就如同,你工作中遇到了問題需要向上反饋,比如先反饋給小組長,然后小組長反饋給上級經(jīng)理,最后經(jīng)理反饋給boss。然后boss感覺這問題太簡單了不需要他親自出手,讓經(jīng)理自己解決吧,然后經(jīng)理又向下交給小組長。小組長一看,這問題不算難,人也比較熱心,于是就幫你把問題解決了。(可能例子不是太恰當哈,意思理解即可)

到此,我們就明白了為什么上邊的代碼會報錯。因為雙親委派機制的存在,去加載我們自己定義的“java.lang.String”類的時候,會最終委派到頂層的啟動類加載器,然后找到了rt.jar包下的“java.lang.String”。找到之后,就直接加載rt.jar包的String類(也就是我們經(jīng)常使用的那個字符串類),不再去向下查找,也就加載不了我們自定義的String類了。由于,rt.jar包下的String類中確實沒有main方法,所以才會有以上的報錯信息。

我們可以試想一下,如果沒有雙親委派機制的存在,那我這段代碼是不是就可以執(zhí)行成功了。如果這樣的話,豈不是說明我可以隨意覆蓋rt.jar包中的類(如String,Integer類等)。這樣的話將會使程序陷入混亂,Java核心包中的類的安全也無法保證。

總結(jié)

以上是生活随笔為你收集整理的java 类加载 双亲委派_Java类加载器和双亲委派机制的全部內(nèi)容,希望文章能夠幫你解決所遇到的問題。

如果覺得生活随笔網(wǎng)站內(nèi)容還不錯,歡迎將生活随笔推薦給好友。