ClassLoader用于在运行时加载class文件。可以从文件系统、网络及其他源加载 Java有三个默认的ClassLoader,分别是:Bootstrap、Extension、System or Application类加载器。每一种类加载器都有预定义的加载路径,见下图。
Java的类加载器遵循三原则:
1. 委派模型:当前ClassLoader优先把类加载请求委派给父ClassLoader加载,如果父ClassLoader找不到class文件或者无法加载,则由子类加载器加载。
2. 可见性:子类加载器可以看到父ClassLoader加载的class,反之,不然;
3. 唯一性:同一个class被父ClassLoader加载后,不会被子类加载器重复加载;
Bootstrap类加载器负责从jre/lib/rt.jar加载标准的JDK class文件。Bootstrap类加载器并没有父类。如果调用rt.jar中的String.class.getClassLoader(),将得到null,这意味着String对应的class文件是由Bootstrap类加载器完成的。
Extension类加载器委派加载请求给Bootstrap加载,如果父类加载器加载不成功,则Extension加载器从jre/lib/ext和java.ext.dirs指定的路径中加载。Extension由sun.misc.Launcher.ExtClassLoader实现。
System or Application类加载器则负责从classpath中加载class文件。它由sun.misc.Launcher.AppClassLoader实现。
下面这幅图显示了,类加载的过程:
代码示例:
public class ClassLoaderSample {
public static void main(String[] args) {
//null代表bootstrap加载器,因为它没有parent参考注释
//从jre/lib/rt.jar中加载class文件
System.out.println(String.class.getClassLoader());
//返回sun.misc.Launcher.ExtClassLoader Extension类加载器
//从jre/lib/ext, java.ext.dirs中加载
System.out.println(ClassLoaderSample.class.getClassLoader().getParent());
//这个并不返回null, 返回sun.misc.Launcher.AppClassLoader,它是应用程序类加载器
//从classpath中加载class文件
ClassLoader classLoader = ClassLoaderSample.class.getClassLoader();
System.out.println(classLoader);
//sun.misc.Launcher.AppClassLoader
classLoader = Thread.currentThread().getContextClassLoader();
System.out.println(classLoader);
InputStream is = classLoader.getResourceAsStream("log4j.properties");
Properties properties = new Properties();
try {
properties.load(is);
System.out.println(properties.getProperty("log4j.rootLogger"));
} catch (IOException e) {
e.printStackTrace();
}
}
}
参考:http://javarevisited.blogspot.hk/2012/12/how-classloader-works-in-java.html