classload之java程式入口sun.misc.Launcher原始碼分析
阿新 • • 發佈:2019-02-02
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