JAVA类加载器原理

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

猜你喜欢

转载自blog.csdn.net/psc928624742/article/details/78207251