用户自定义类加载器

75 阅读1分钟

自定义类加载器的使用原因

隔离加载类

可能在一个大项目中,有路径名和包名都一样的情况,但是这是不同的类,如果用一个加载器进行加载由于加载器命名空间的问题,就会导致不同的类产生覆盖

修改类的加载方式

其实双亲委派机制是一种加载方式,而不是强制性的,如果想换也能换,参考loadclass源码

扩展加载源

防止源码被泄露

为了防止.class文件中的字节码被泄露,我们可以做一些加密处理,因此对应于类的加载器就应该进行相应的改造,以加载被加密后的字节码文件 。

自定义类加载器的两种方式

首先给出classLoader加载器的源码

synchronized (getClassLoadingLock(name)) {
    // First, check if the class has already been loaded
    Class<?> c = findLoadedClass(name);
    if (c == null) {
        long t0 = System.nanoTime();
        try {
            if (parent != null) {
                c = parent.loadClass(name, false);
            } else {
                c = findBootstrapClassOrNull(name);
            }
        } catch (ClassNotFoundException e) {
            // ClassNotFoundException thrown if class not found
            // from the non-null parent class loader
        }

        if (c == null) {
            // If still not found, then invoke findClass in order
            // to find the class.
            long t1 = System.nanoTime();
            c = findClass(name);

            // this is the defining class loader; record the stats
            sun.misc.PerfCounter.getParentDelegationTime().addTime(t1 - t0);
            sun.misc.PerfCounter.getFindClassTime().addElapsedTimeFrom(t1);
            sun.misc.PerfCounter.getFindClasses().increment();
        }
    }
    if (resolve) {
        resolveClass(c);
    }

在classLoader关于类加载的方法主要是loadclass,在这个类中给出了双亲委派机制。在findClass中给出了本类的加载方式。

loadClass方法

这个方法一般不重写,这个方法内部包含着双亲委派模型的类加载方式。

findClass方法

这个方法是真正进行类加载的方法

结尾

只要继承了ClassLoader这个抽象类的类加载器,其父类加载器都是App加载器。
看以下源码

protected ClassLoader() {
    this(checkCreateClassLoader(), getSystemClassLoader());
}