classLoader.getResources

簡單例子

    @Test
    public void urlLoadTest() throws IOException {
            System.out.println(System.getProperty("java.class.path"));
            System.out.println(System.getProperty("java.ext.dirs"));
            URLClassLoader loader = new URLClassLoader(new URL[] { new URL("file:D:\\workspaces\\") });
            Enumeration<URL> result= loader.getResources("META-INF/spring.handlers");
            List<URL> rResult=new ArrayList<>();
            while (result.hasMoreElements()){
                rResult.add(result.nextElement());
            }
            System.out.println(rResult);
    }

執(zhí)行結(jié)果

C:\Program Files\JetBrains\xxx\lib\idea_rt.jar;C:\Program Files\JetBrains\xxx\plugins\junit\lib\junit-rt.jar;C:\Program Files\JetBrains\xxx\plugins\junit\lib\junit5-rt.jar;C:\Program Files\Java\Java\jdk1.8.0_111\jre\lib\charsets.jar;C:\Program Files\Java\Java\jdk1.8.0_111\jre\lib\deploy.jar;C:\Program Files\Java\Java\jdk1.8.0_111\jre\lib\ext\access-bridge-64.jar;C:\Program Files\Java\Java\jdk1.8.0_111\jre\lib\ext\cldrdata.jar;C:\Program Files\Java\Java\jdk1.8.0_111\jre\lib\ext\dnsns.jar;C:\Program Files\Java\Java\jdk1.8.0_111\jre\lib\ext\jaccess.jar;C:\Program Files\Java\Java\jdk1.8.0_111\jre\lib\ext\jfxrt.jar;C:\Program Files\Java\Java\jdk1.8.0_111\jre\lib\ext\localedata.jar;C:\Program Files\Java\Java\jdk1.8.0_111\jre\lib\ext\nashorn.jar;C:\Program Files\Java\Java\jdk1.8.0_111\jre\lib\ext\sunec.jar;C:\Program Files\Java\Java\jdk1.8.0_111\jre\lib\ext\sunjce_provider.jar;C:\Program Files\Java\Java\jdk1.8.0_111\jre\lib\ext\sunmscapi.jar;C:\Program Files\Java\Java\jdk1.8.0_111\jre\lib\ext\sunpkcs11.jar;C:\Program Files\Java\Java\jdk1.8.0_111\jre\lib\ext\zipfs.jar;C:\Program Files\Java\Java\jdk1.8.0_111\jre\lib\javaws.jar;C:\Program Files\Java\Java\jdk1.8.0_111\jre\lib\jce.jar;C:\Program Files\Java\Java\jdk1.8.0_111\jre\lib\jfr.jar;C:\Program Files\Java\Java\jdk1.8.0_111\jre\lib\jfxswt.jar;C:\Program Files\Java\Java\jdk1.8.0_111\jre\lib\jsse.jar;C:\Program Files\Java\Java\jdk1.8.0_111\jre\lib\management-agent.jar;C:\Program Files\Java\Java\jdk1.8.0_111\jre\lib\plugin.jar;C:\Program Files\Java\Java\jdk1.8.0_111\jre\lib\resources.jar;C:\Program Files\Java\Java\jdk1.8.0_111\jre\lib\rt.jar;D:\dev\project\private\project\quicklyCreateSpringMvc\miniSpring1\target\test-classes;D:\dev\project\private\project\quicklyCreateSpringMvc\miniSpring1\target\classes;C:\java環(huán)境\repository\maven\org\springframework\spring-webmvc\4.3.25.RELEASE\spring-webmvc-4.3.25.RELEASE.jar;C:\java環(huán)境\repository\maven\org\springframework\spring-aop\4.3.25.RELEASE\spring-aop-4.3.25.RELEASE.jar;C:\java環(huán)境\repository\maven\org\springframework\spring-beans\4.3.25.RELEASE\spring-beans-4.3.25.RELEASE.jar;C:\java環(huán)境\repository\maven\org\springframework\spring-context\4.3.25.RELEASE\spring-context-4.3.25.RELEASE.jar;C:\java環(huán)境\repository\maven\org\springframework\spring-core\4.3.25.RELEASE\spring-core-4.3.25.RELEASE.jar;C:\java環(huán)境\repository\maven\commons-logging\commons-logging\1.2\commons-logging-1.2.jar;C:\java環(huán)境\repository\maven\org\springframework\spring-expression\4.3.25.RELEASE\spring-expression-4.3.25.RELEASE.jar;C:\java環(huán)境\repository\maven\org\springframework\spring-web\4.3.25.RELEASE\spring-web-4.3.25.RELEASE.jar;C:\java環(huán)境\repository\maven\ch\qos\logback\logback-classic\1.2.3\logback-classic-1.2.3.jar;C:\java環(huán)境\repository\maven\ch\qos\logback\logback-core\1.2.3\logback-core-1.2.3.jar;C:\java環(huán)境\repository\maven\org\slf4j\slf4j-api\1.7.25\slf4j-api-1.7.25.jar;C:\java環(huán)境\repository\maven\junit\junit\4.12\junit-4.12.jar;C:\java環(huán)境\repository\maven\org\hamcrest\hamcrest-core\1.3\hamcrest-core-1.3.jar;C:\java環(huán)境\repository\maven\org\aspectj\aspectjrt\1.8.9\aspectjrt-1.8.9.jar;C:\java環(huán)境\repository\maven\org\aspectj\aspectjweaver\1.8.9\aspectjweaver-1.8.9.jar;C:\Program Files\JetBrains\xxx\lib\idea_rt.jar
C:\Program Files\Java\Java\jdk1.8.0_111\jre\lib\ext;C:\Windows\Sun\Java\lib\ext
[jar:file:/C:/java%e7%8e%af%e5%a2%83/repository/maven/org/springframework/spring-webmvc/4.3.25.RELEASE/spring-webmvc-4.3.25.RELEASE.jar!/META-INF/spring.handlers, jar:file:/C:/java%e7%8e%af%e5%a2%83/repository/maven/org/springframework/spring-aop/4.3.25.RELEASE/spring-aop-4.3.25.RELEASE.jar!/META-INF/spring.handlers, jar:file:/C:/java%e7%8e%af%e5%a2%83/repository/maven/org/springframework/spring-beans/4.3.25.RELEASE/spring-beans-4.3.25.RELEASE.jar!/META-INF/spring.handlers, jar:file:/C:/java%e7%8e%af%e5%a2%83/repository/maven/org/springframework/spring-context/4.3.25.RELEASE/spring-context-4.3.25.RELEASE.jar!/META-INF/spring.handlers]

其中l(wèi)oader層級

ExtClassLoader
APPClassLoader
URLClassLoader

以上層級是如何來的庆杜?我們可以看到最終是由Launcher 實現(xiàn)

public class URLClassLoader extends SecureClassLoader implements Closeable {
    //指定classLoader
    public URLClassLoader(URL[] urls, ClassLoader parent) {
        super(parent);
        ....
    }
    //使用默認
    public URLClassLoader(URL[] urls) {
        super();
        ....
    }
}

public class SecureClassLoader extends ClassLoader {
    protected SecureClassLoader() {
        super();
    }
}

public abstract class ClassLoader {
    protected ClassLoader() {
        this(checkCreateClassLoader(), getSystemClassLoader());
    }

    
    public static ClassLoader getSystemClassLoader() {
        initSystemClassLoader();
        ....
        return scl;
    }

    //默認loader由Launcher產(chǎn)生
    private static synchronized void initSystemClassLoader() {
            sun.misc.Launcher l = sun.misc.Launcher.getLauncher();
            ....
            scl = l.getClassLoader();
    }

    //最終賦值
    private ClassLoader(Void unused, ClassLoader parent) {
        this.parent = parent;
        ....
    }

}


public class Launcher {
    private static Launcher launcher = new Launcher();
    //最終實現(xiàn)
    public Launcher() {
        Launcher.ExtClassLoader var1= Launcher.ExtClassLoader.getExtClassLoader();
        this.loader = Launcher.AppClassLoader.getAppClassLoader(var1);
        Thread.currentThread().setContextClassLoader(this.loader);
    }
    public static Launcher getLauncher() {
        return launcher;
    }
}

那么在getResources時ExtClassLoader、APPClassLoader涵叮、URLClassLoader三個loader怎么協(xié)作的甚亭?

    public Enumeration<URL> getResources(String name) throws IOException {
        @SuppressWarnings("unchecked")
        Enumeration<URL>[] tmp = (Enumeration<URL>[]) new Enumeration<?>[2];
        if (parent != null) {
            tmp[0] = parent.getResources(name);
        } else {
            tmp[0] = getBootstrapResources(name);
        }
        tmp[1] = findResources(name);

        return new CompoundEnumeration<>(tmp);
    }

可以看到芭商,其實是遞歸獲取parent-loader的getResources的內(nèi)容,最終合并到一起。

URLClassLoader loader = new URLClassLoader(new URL[] { new URL("file:D:\\workspaces\\") });
Enumeration<URL> result= loader.getResources("META-INF/spring.handlers");

所以再愈,其實上面代碼,等效于分別獲取ExtClassLoader护戳、APPClassLoader翎冲、URLClassLoader的findResources方法合并結(jié)果。

ExtClassLoader處理路徑

    static class ExtClassLoader extends URLClassLoader {
        public static Launcher.ExtClassLoader getExtClassLoader() throws IOException {
            final File[] var0 = getExtDirs();
            ...
        }

        private static File[] getExtDirs() {
            String var0 = System.getProperty("java.ext.dirs");
            File[] var1;
            if (var0 != null) {
                StringTokenizer var2 = new StringTokenizer(var0, File.pathSeparator);
                ..
            } else {
                var1 = new File[0];
            }

            return var1;
        }
    }

我們觀察到兩個點媳荒,

  • 其實ExtClassLoader 繼承自URLClassLoader (這是代碼結(jié)構(gòu)抗悍,而非parent,說明只是部分重寫了URLClassLoader功能钳枕。)
  • String var0 = System.getProperty("java.ext.dirs")缴渊,其實ExtClassLoader 就是對這個路徑進行處理。

AppClassLoader處理路徑

    static class AppClassLoader extends URLClassLoader {
        final URLClassPath ucp = SharedSecrets.getJavaNetAccess().getURLClassPath(this);

        public static ClassLoader getAppClassLoader(final ClassLoader var0) throws IOException {
            final String var1 = System.getProperty("java.class.path");
            ..
        }

處理路徑為System.getProperty("java.class.path")鱼炒,即項目引用的各種lib里的jar包;

UrlClassLoader處理路徑

通過參數(shù)外面?zhèn)魅?/p>

 URLClassLoader loader = new URLClassLoader(new URL[] { new URL("file:D:\\workspaces\\") });

URLClassLoader.findResources方法

上面說到衔沼,getResources方法等效于等效于分別獲取ExtClassLoader、APPClassLoader昔瞧、URLClassLoader的findResources方法合并結(jié)果指蚁。

public class URLClassLoader extends SecureClassLoader implements Closeable {
    public Enumeration<URL> findResources(final String name)
        throws IOException
    {
        final Enumeration<URL> e = ucp.findResources(name, true);
        ...
    }
}

public class URLClassPath {
    public Enumeration<URL> findResources(final String var1, final boolean var2) {
        return new Enumeration<URL>() {
            private int index = 0;
            private int[] cache = URLClassPath.this.getLookupCache(var1);
            private URL url = null;

            private boolean next() {
                if (this.url != null) {
                    return true;
                } else {
                    do {
                        URLClassPath.Loader var1x;
                       //獲取相應(yīng)loader,這一步可以理解為獲取目錄地址自晰,例如java.class.path會有很多目錄
                        if ((var1x = URLClassPath.this.getNextLoader(this.cache, this.index++)) == null) {
                            return false;
                        }
                       //獲取相應(yīng)拼接
                        this.url = var1x.findResource(var1, var2);
                    } while(this.url == null);

                    return true;
                }
            }
            ...
    }


    private synchronized URLClassPath.Loader getNextLoader(int[] var1, int var2) {
        if (this.closed) {
            return null;
        } else if (var1 != null) {
            ...
        } else {
            return this.getLoader(var2);
        }
    }

    private synchronized URLClassPath.Loader getLoader(int var1) {
        if (this.closed) {
            return null;
        } else {
            //循環(huán)完成以后才執(zhí)行
            while(this.loaders.size() < var1 + 1) {
            }
            //最終實現(xiàn)
            return (URLClassPath.Loader)this.loaders.get(var1);
        }
    }
}

其中
var1x.findResource
三個實現(xiàn)了類
FileLoader:直接從文件流中獲取
JarLoader:從jar中讀取凝化,基于zip壓縮,拼接路徑獲取
Loader:缀磕。缘圈。

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
  • 序言:七十年代末,一起剝皮案震驚了整個濱河市袜蚕,隨后出現(xiàn)的幾起案子糟把,更是在濱河造成了極大的恐慌,老刑警劉巖牲剃,帶你破解...
    沈念sama閱讀 216,997評論 6 502
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件遣疯,死亡現(xiàn)場離奇詭異,居然都是意外死亡凿傅,警方通過查閱死者的電腦和手機缠犀,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 92,603評論 3 392
  • 文/潘曉璐 我一進店門数苫,熙熙樓的掌柜王于貴愁眉苦臉地迎上來,“玉大人辨液,你說我怎么就攤上這事虐急。” “怎么了滔迈?”我有些...
    開封第一講書人閱讀 163,359評論 0 353
  • 文/不壞的土叔 我叫張陵止吁,是天一觀的道長。 經(jīng)常有香客問我燎悍,道長敬惦,這世上最難降的妖魔是什么? 我笑而不...
    開封第一講書人閱讀 58,309評論 1 292
  • 正文 為了忘掉前任谈山,我火速辦了婚禮俄删,結(jié)果婚禮上,老公的妹妹穿的比我還像新娘奏路。我一直安慰自己畴椰,他們只是感情好,可當我...
    茶點故事閱讀 67,346評論 6 390
  • 文/花漫 我一把揭開白布思劳。 她就那樣靜靜地躺著迅矛,像睡著了一般。 火紅的嫁衣襯著肌膚如雪潜叛。 梳的紋絲不亂的頭發(fā)上,一...
    開封第一講書人閱讀 51,258評論 1 300
  • 那天壶硅,我揣著相機與錄音威兜,去河邊找鬼。 笑死庐椒,一個胖子當著我的面吹牛椒舵,可吹牛的內(nèi)容都是我干的。 我是一名探鬼主播约谈,決...
    沈念sama閱讀 40,122評論 3 418
  • 文/蒼蘭香墨 我猛地睜開眼笔宿,長吁一口氣:“原來是場噩夢啊……” “哼!你這毒婦竟也來了棱诱?” 一聲冷哼從身側(cè)響起泼橘,我...
    開封第一講書人閱讀 38,970評論 0 275
  • 序言:老撾萬榮一對情侶失蹤,失蹤者是張志新(化名)和其女友劉穎迈勋,沒想到半個月后炬灭,有當?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體,經(jīng)...
    沈念sama閱讀 45,403評論 1 313
  • 正文 獨居荒郊野嶺守林人離奇死亡靡菇,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點故事閱讀 37,596評論 3 334
  • 正文 我和宋清朗相戀三年重归,在試婚紗的時候發(fā)現(xiàn)自己被綠了米愿。 大學(xué)時的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片。...
    茶點故事閱讀 39,769評論 1 348
  • 序言:一個原本活蹦亂跳的男人離奇死亡鼻吮,死狀恐怖育苟,靈堂內(nèi)的尸體忽然破棺而出,到底是詐尸還是另有隱情椎木,我是刑警寧澤违柏,帶...
    沈念sama閱讀 35,464評論 5 344
  • 正文 年R本政府宣布,位于F島的核電站拓哺,受9級特大地震影響勇垛,放射性物質(zhì)發(fā)生泄漏。R本人自食惡果不足惜士鸥,卻給世界環(huán)境...
    茶點故事閱讀 41,075評論 3 327
  • 文/蒙蒙 一闲孤、第九天 我趴在偏房一處隱蔽的房頂上張望。 院中可真熱鬧烤礁,春花似錦讼积、人聲如沸。這莊子的主人今日做“春日...
    開封第一講書人閱讀 31,705評論 0 22
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽。三九已至鲤脏,卻和暖如春们颜,著一層夾襖步出監(jiān)牢的瞬間,已是汗流浹背猎醇。 一陣腳步聲響...
    開封第一講書人閱讀 32,848評論 1 269
  • 我被黑心中介騙來泰國打工窥突, 沒想到剛下飛機就差點兒被人妖公主榨干…… 1. 我叫王不留,地道東北人硫嘶。 一個月前我還...
    沈念sama閱讀 47,831評論 2 370
  • 正文 我出身青樓阻问,卻偏偏與公主長得像,于是被迫代替她去往敵國和親沦疾。 傳聞我的和親對象是個殘疾皇子称近,可洞房花燭夜當晚...
    茶點故事閱讀 44,678評論 2 354

推薦閱讀更多精彩內(nèi)容

  • ClassLoader翻譯過來就是類加載器,普通的java開發(fā)者其實用到的不多哮塞,但對于某些框架開發(fā)者來說卻非常常見...
    時待吾閱讀 1,073評論 0 1
  • ClassLoader就是類加載器刨秆。ClassLoader的作用就是將class文件加載到j(luò)vm虛擬機中去。jvm...
    你需要一臺永動機閱讀 96評論 0 0
  • 1彻桃、classLoader 類加載器坛善,將class文件加載到JVM虛擬機內(nèi)存中,使得程序可以運行。通常情況下眠屎,JV...
    helloWorld_1118閱讀 2,213評論 0 2
  • 本篇文章已授權(quán)微信公眾號 guolin_blog (郭霖)獨家發(fā)布 ClassLoader翻譯過來就是類加載器剔交,普...
    尼爾君閱讀 660評論 1 0
  • 轉(zhuǎn)發(fā):本篇文章已授權(quán)微信公眾號 guolin_blog (郭霖)獨家發(fā)布 ClassLoader翻譯過來就是類加載...
    尼爾君閱讀 532評論 0 1