1. 程式人生 > >classload之java程式入口sun.misc.Launcher原始碼分析

classload之java程式入口sun.misc.Launcher原始碼分析

java程式的入口就是sun.misc.Launcher了,這個類裡面又繼承了ExtClassLoader和AppClassLoader和bootstrap的url路徑。


1、Launch類初始化

private static Launcher launcher = new Launcher();
private static String bootClassPath =  System.getProperty("sun.boot.class.path");

    public static Launcher getLauncher() {
        return launcher;
    }

    private ClassLoader loader;

    public Launcher() {
        // Create the extension class loader
        ClassLoader extcl;
        try {
            extcl = ExtClassLoader.getExtClassLoader();
        } catch (IOException e) {
            throw new InternalError(
                "Could not create extension class loader");
        }

        // Now create the class loader to use to launch the application
        try {
            loader = AppClassLoader.getAppClassLoader(extcl);
        } catch (IOException e) {
            throw new InternalError(
                "Could not create application class loader");
        }

        // Also set the context class loader for the primordial thread.
        Thread.currentThread().setContextClassLoader(loader);

        // Finally, install a security manager if requested
        String s = System.getProperty("java.security.manager");
        ......
    }

    /*
     * Returns the class loader used to launch the main application.
     */
    public ClassLoader getClassLoader() {
        return loader;
    }

可以看到Launcher類初始化時,先初始化了個ExtClassLoader,然後又初始化了個AppClassLoader,然後把ExtClassLoader作為AppClassLoader的父loader。

ExtClassLoader沒有指定父類,即表明,父類是BootstrapClassLoader。

把初始化的AppClassLoader 作為全域性變數儲存起來,並設定到當前執行緒contextClassLoader。

每個執行緒例項可以設定一個contextClassLoader

2、bootClassPath

Launcher 類有個全域性的變數private static String  bootClassPath =        System.getProperty("sun.boot.class.path")  表示bootclassloader去哪裡載入類和資源,看以下測試。
@Test
	public void test3(){
		System.out.println("bootstrap classload----------------------");
		final String s = System.getProperty("sun.boot.class.path");
    	System.out.println(s);
		final File[] path = (s == null) ? new File[0] : getClassPath(s);
		for(File f : path){
			System.out.println(f);
		}
		System.out.println();
		sun.misc.Launcher launcher = sun.misc.Launcher.getLauncher();
		System.out.println(launcher.getClass().getClassLoader());
		
	}
輸出:
bootstrap classload----------------------
C:\Program Files\Java\jre1.8.0_77\lib\resources.jar;C:\Program Files\Java\jre1.8.0_77\lib\rt.jar;C:\Program Files\Java\jre1.8.0_77\lib\sunrsasign.jar;C:\Program Files\Java\jre1.8.0_77\lib\jsse.jar;C:\Program Files\Java\jre1.8.0_77\lib\jce.jar;C:\Program Files\Java\jre1.8.0_77\lib\charsets.jar;C:\Program Files\Java\jre1.8.0_77\lib\jfr.jar;C:\Program Files\Java\jre1.8.0_77\classes
C:\Program Files\Java\jre1.8.0_77\lib\resources.jar
C:\Program Files\Java\jre1.8.0_77\lib\rt.jar
C:\Program Files\Java\jre1.8.0_77\lib\sunrsasign.jar
C:\Program Files\Java\jre1.8.0_77\lib\jsse.jar
C:\Program Files\Java\jre1.8.0_77\lib\jce.jar
C:\Program Files\Java\jre1.8.0_77\lib\charsets.jar
C:\Program Files\Java\jre1.8.0_77\lib\jfr.jar
C:\Program Files\Java\jre1.8.0_77\classes

null


3、ExtClassLoader

extclassloader作為java中間的一個loader,例項化之後就放到classloader鏈裡面了。
@Test
	public void test4(){
		System.out.println("ext classload----------------------");
		final String s = System.getProperty("java.ext.dirs");//對應路徑
		System.out.println(s);
		
        File[] dirs;
        if (s != null) {
            StringTokenizer st =
                new StringTokenizer(s, File.pathSeparator);
            int count = st.countTokens();
            dirs = new File[count];
            for (int i = 0; i < count; i++) {
                dirs[i] = new File(st.nextToken());
            }
        } else {
            dirs = new File[0];
        }
		
        for(File f:dirs){
        	System.out.println(f.getAbsolutePath());
        }
	}
輸出:
ext classload----------------------
C:\Program Files\Java\jre1.8.0_77\lib\ext;C:\Windows\Sun\Java\lib\ext
C:\Program Files\Java\jre1.8.0_77\lib\ext
C:\Windows\Sun\Java\lib\ext

extclassloader的url有點特殊,System.getProperty("java.ext.dirs")得到的是路徑,jvm會把路徑下面的所有檔案都作為一個單獨的url處理(一層路徑)。
private static URL[] getExtURLs(File[] dirs) throws IOException {
            Vector<URL> urls = new Vector<URL>();
            for (int i = 0; i < dirs.length; i++) {
                String[] files = dirs[i].list();
                if (files != null) {
                    for (int j = 0; j < files.length; j++) {
                        if (!files[j].equals("meta-index")) {
                            File f = new File(dirs[i], files[j]);
                            urls.add(getFileURL(f));
                        }
                    }
                }
            }
            URL[] ua = new URL[urls.size()];
            urls.copyInto(ua);
            return ua;
        }

4、appclassloader

@Test
	public void test2(){
		System.out.println("app classload----------------------");
		final String s = System.getProperty("java.class.path");
		System.out.println(s);
        final File[] path = (s == null) ? new File[0] : getClassPath(s);
        for(File f : path){
        	System.out.println(f);
        }
	}

輸出:
app classload----------------------
E:\java\my_workspace\myclassload\bin;E:\program\eclipse4.4-navi-32_2\eclipse4.4-navi-32\plugins\org.junit_4.11.0.v201303080030\junit.jar;E:\program\eclipse4.4-navi-32_2\eclipse4.4-navi-32\plugins\org.hamcrest.core_1.3.0.v201303031735.jar;/E:/program/eclipse4.4-navi-32_2/eclipse4.4-navi-32/configuration/org.eclipse.osgi/362/0/.cp/;/E:/program/eclipse4.4-navi-32_2/eclipse4.4-navi-32/configuration/org.eclipse.osgi/361/0/.cp/
E:\java\my_workspace\myclassload\bin
E:\program\eclipse4.4-navi-32_2\eclipse4.4-navi-32\plugins\org.junit_4.11.0.v201303080030\junit.jar
E:\program\eclipse4.4-navi-32_2\eclipse4.4-navi-32\plugins\org.hamcrest.core_1.3.0.v201303031735.jar
E:\program\eclipse4.4-navi-32_2\eclipse4.4-navi-32\configuration\org.eclipse.osgi\362\0\.cp
E:\program\eclipse4.4-navi-32_2\eclipse4.4-navi-32\configuration\org.eclipse.osgi\361\0\.cp