一区二区三区日韩精品-日韩经典一区二区三区-五月激情综合丁香婷婷-欧美精品中文字幕专区

分享

類加載器的工作原理

 鳳凰苑兇真 2017-05-13
本文由 ImportNew - 唐小娟 翻譯自 Javarevisited。歡迎加入翻譯小組。轉(zhuǎn)載請見文末要求。

Java類加載器的作用就是在運行時加載類。Java類加載器基于三個機制:委托、可見性和單一性。委托機制是指將加載一個類的請求交給父類加載器,如果這個父類加載器不能夠找到或者加載這個類,那么再加載它。可見性的原理是子類的加載器可以看見所有的父類加載器加載的類,而父類加載器看不到子類加載器加載的類。單一性原理是指僅加載一個類一次,這是由委托機制確保子類加載器不會再次加載父類加載器加載過的類。正確理解類加載器能夠幫你解決NoClassDefFoundError和java.lang.ClassNotFoundException,因為它們和類的加載相關。類加載器通常也是比較高級的Java面試中的重要考題,Java類加載器和工作原理以及classpath如何運作的經(jīng)常被問到。Java面試題中也經(jīng)常出現(xiàn)“一個類是否能被兩個不同類加載器加載”這樣的問題。這篇教程中,我們將學到類加載器是什么,它的工作原理以及一些關于類加載器的知識點。

什么是類加載器

類加載器是一個用來加載類文件的類。Java源代碼通過javac編譯器編譯成類文件。然后JVM來執(zhí)行類文件中的字節(jié)碼來執(zhí)行程序。類加載器負責加載文件系統(tǒng)、網(wǎng)絡或其他來源的類文件。有三種默認使用的類加載器:Bootstrap類加載器、Extension類加載器和System類加載器(或者叫作Application類加載器)。每種類加載器都有設定好從哪里加載類。

  • Bootstrap類加載器負責加載rt.jar中的JDK類文件,它是所有類加載器的父加載器。Bootstrap類加載器沒有任何父類加載器,如果你調(diào)用String.class.getClassLoader(),會返回null,任何基于此的代碼會拋出NUllPointerException異常。Bootstrap加載器被稱為初始類加載器。
  • 而Extension將加載類的請求先委托給它的父加載器,也就是Bootstrap,如果沒有成功加載的話,再從jre/lib/ext目錄下或者java.ext.dirs系統(tǒng)屬性定義的目錄下加載類。Extension加載器由sun.misc.Launcher$ExtClassLoader實現(xiàn)。
  • 第三種默認的加載器就是System類加載器(又叫作Application類加載器)了。它負責從classpath環(huán)境變量中加載某些應用相關的類,classpath環(huán)境變量通常由-classpath或-cp命令行選項來定義,或者是JAR中的Manifest的classpath屬性。Application類加載器是Extension類加載器的子加載器。通過sun.misc.Launcher$AppClassLoader實現(xiàn)。

除了Bootstrap類加載器是大部分由C來寫的,其他的類加載器都是通過java.lang.ClassLoader來實現(xiàn)的。

總結一下,下面是三種類加載器加載類文件的地方:

1) Bootstrap類加載器 – JRE/lib/rt.jar

2) Extension類加載器 – JRE/lib/ext或者java.ext.dirs指向的目錄

3) Application類加載器 – CLASSPATH環(huán)境變量, 由-classpath或-cp選項定義,或者是JAR中的Manifest的classpath屬性定義.

類加載器的工作原理

我之前已經(jīng)提到過了,類加載器的工作原理基于三個機制:委托、可見性和單一性。這一節(jié),我們來詳細看看這些規(guī)則,并用一個實例來理解工作原理。下面顯示的是類加載器使用委托機制的工作原理。

委托機制

當一個類加載和初始化的時候,類僅在有需要加載的時候被加載。假設你有一個應用需要的類叫作Abc.class,首先加載這個類的請求由Application類加載器委托給它的父類加載器Extension類加載器,然后再委托給Bootstrap類加載器。Bootstrap類加載器會先看看rt.jar中有沒有這個類,因為并沒有這個類,所以這個請求由回到Extension類加載器,它會查看jre/lib/ext目錄下有沒有這個類,如果這個類被Extension類加載器找到了,那么它將被加載,而Application類加載器不會加載這個類;而如果這個類沒有被Extension類加載器找到,那么再由Application類加載器從classpath中尋找。記住classpath定義的是類文件的加載目錄,而PATH是定義的是可執(zhí)行程序如javac,java等的執(zhí)行路徑。

可見性機制

根據(jù)可見性機制,子類加載器可以看到父類加載器加載的類,而反之則不行。所以下面的例子中,當Abc.class已經(jīng)被Application類加載器加載過了,然后如果想要使用Extension類加載器加載這個類,將會拋出java.lang.ClassNotFoundException異常。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
package test;
    import java.util.logging.Level;
    import java.util.logging.Logger;
    /**
     * Java program to demonstrate How ClassLoader works in Java,
     * in particular about visibility principle of ClassLoader.
     *
     * @author Javin Paul
     */
    public class ClassLoaderTest {
        public static void main(String args[]) {
            try {         
                //printing ClassLoader of this class
                System.out.println("ClassLoaderTest.getClass().getClassLoader() : "
                                     + ClassLoaderTest.class.getClassLoader());
                //trying to explicitly load this class again using Extension class loader
                Class.forName("test.ClassLoaderTest", true
                                ,  ClassLoaderTest.class.getClassLoader().getParent());
            } catch (ClassNotFoundException ex) {
                Logger.getLogger(ClassLoaderTest.class.getName()).log(Level.SEVERE, null, ex);
            }
        }
    }

輸出:

1
2
3
4
5
6
7
8
9
10
11
12
13
ClassLoaderTest.getClass().getClassLoader() : sun.misc.Launcher$AppClassLoader@601bb1
16/08/2012 2:43:48 AM test.ClassLoaderTest main
SEVERE: null
java.lang.ClassNotFoundException: test.ClassLoaderTest
        at java.net.URLClassLoader$1.run(URLClassLoader.java:202)
        at java.security.AccessController.doPrivileged(Native Method)
        at java.net.URLClassLoader.findClass(URLClassLoader.java:190)
        at sun.misc.Launcher$ExtClassLoader.findClass(Launcher.java:229)
        at java.lang.ClassLoader.loadClass(ClassLoader.java:306)
        at java.lang.ClassLoader.loadClass(ClassLoader.java:247)
        at java.lang.Class.forName0(Native Method)
        at java.lang.Class.forName(Class.java:247)
        at test.ClassLoaderTest.main(ClassLoaderTest.java:29)

單一性機制

根據(jù)這個機制,父加載器加載過的類不能被子加載器加載第二次。雖然重寫違反委托和單一性機制的類加載器是可能的,但這樣做并不可取。你寫自己的類加載器的時候應該嚴格遵守這三條機制。

如何顯式的加載類

Java提供了顯式加載類的API:Class.forName(classname)和Class.forName(classname, initialized, classloader)。就像上面的例子中,你可以指定類加載器的名稱以及要加載的類的名稱。類的加載是通過調(diào)用java.lang.ClassLoader的loadClass()方法,而loadClass()方法則調(diào)用了findClass()方法來定位相應類的字節(jié)碼。在這個例子中Extension類加載器使用了java.net.URLClassLoader,它從JAR和目錄中進行查找類文件,所有以”/”結尾的查找路徑被認為是目錄。如果findClass()沒有找到那么它會拋出java.lang.ClassNotFoundException異常,而如果找到的話則會調(diào)用defineClass()將字節(jié)碼轉(zhuǎn)化成類實例,然后返回。

什么地方使用類加載器

類加載器是個很強大的概念,很多地方被運用。最經(jīng)典的例子就是AppletClassLoader,它被用來加載Applet使用的類,而Applets大部分是在網(wǎng)上使用,而非本地的操作系統(tǒng)使用。使用不同的類加載器,你可以從不同的源地址加載同一個類,它們被視為不同的類。J2EE使用多個類加載器加載不同地方的類,例如WAR文件由Web-app類加載器加載,而EJB-JAR中的類由另外的類加載器加載。有些服務器也支持熱部署,這也由類加載器實現(xiàn)。你也可以使用類加載器來加載數(shù)據(jù)庫或者其他持久層的數(shù)據(jù)。

以上是關于類加載器的工作原理。我們已經(jīng)知道了委托、可見性以及單一性原理,這些對于調(diào)試類加載器相關問題時至關重要。這些對于Java程序員和架構師來說都是必不可少的知識。

原文鏈接: Javarevisited 翻譯: ImportNew.com - 唐小娟
譯文鏈接: http://www./6581.html
[ 轉(zhuǎn)載請保留原文出處、譯者和譯文鏈接。]

關于作者: 唐小娟

一名在路上的程旭媛

查看唐小娟的更多文章 >> 

    本站是提供個人知識管理的網(wǎng)絡存儲空間,所有內(nèi)容均由用戶發(fā)布,不代表本站觀點。請注意甄別內(nèi)容中的聯(lián)系方式、誘導購買等信息,謹防詐騙。如發(fā)現(xiàn)有害或侵權內(nèi)容,請點擊一鍵舉報。
    轉(zhuǎn)藏 分享 獻花(0

    0條評論

    發(fā)表

    請遵守用戶 評論公約

    類似文章 更多

    日韩欧美精品一区二区三区| 日韩欧美综合在线播放| 老司机精品在线你懂的| 无套内射美女视频免费在线观看| 五月婷日韩中文字幕四虎| 亚洲天堂精品一区二区| 在线视频免费看你懂的| 日本东京热加勒比一区二区| 人妻巨大乳一二三区麻豆| 中文日韩精品视频在线| 午夜资源在线观看免费高清| 亚洲精品黄色片中文字幕| 大尺度激情福利视频在线观看| 后入美臀少妇一区二区| 国产又粗又长又爽又猛的视频| 亚洲a码一区二区三区| 国产av一二三区在线观看| 人人妻人人澡人人夜夜| 99免费人成看国产片| 国产一区二区三区丝袜不卡| 字幕日本欧美一区二区| 人妻熟女欲求不满一区二区| 黄色片一区二区在线观看| 亚洲三级视频在线观看免费| 真实偷拍一区二区免费视频| 人妻少妇系列中文字幕| 欧美老太太性生活大片| 日韩精品免费一区三区| 日韩国产欧美中文字幕| 午夜福利视频六七十路熟女| 中文字幕人妻av不卡| 亚洲一区二区三区免费的视频| 欧美在线观看视频免费不卡| 日韩中文字幕狠狠人妻| 中文字日产幕码三区国产| 91福利免费一区二区三区| 国产福利在线播放麻豆| 日本亚洲精品在线观看| 欧美一级片日韩一级片| 最好看的人妻中文字幕| 久久中文字幕中文字幕中文|