classload之java程序入口sun.misc.Launcher源码分析

时间:2022-11-20 19:39:14

java程序的入口就是sun.misc.Launcher了,这个类里面又继承了ExtClassLoader和AppClassLoader和bootstrap的url路径。

classload之java程序入口sun.misc.Launcher源码分析

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