乐趣区

关于jvm:面试八股文五类的加载和双亲委派机制

一、什么是类的加载?

答:java 时候两步的,编译和运行,类的加载指的是将编译生成的类的 class 文件读入内存,并为之创立一个 java.lang.Class 对象。类的加载过程是由类加载器来实现,而类加载器由 JVM 提供。

二、类的加载器有哪些?

1.Bootstrap ClassLoader:负责加载 %JAVA_HOME%/jre/lib 下的 jar 包,或者说 jdk 的本地 jar 包,比方 rt.jar 解压后中就蕴含了咱们罕用的 java 类的 class 文件

2.Extension ClassLoader:负责加载 %JAVA_HOME%/jre/ext 或者 java.ext.dirs 零碎相熟指定的目录的 jar 包,或者说 jdk 中外部实现的扩大类
3.System ClassLoader:自定义加载器的父类,负责加载 ClassPath 下的类文件(程序中的类文件)

三、什么是双亲委派机制?

1. 目标:为了避免内存中存在多份同样的字节码(平安),他不会尝试本人加载类,而是把申请委托给父加载器去实现, 顺次向上
2. 解释:只有当父加载器在本人搜寻范畴内找不到特定的类时 (即 ClassNotFoundException), 子加载器才会尝试本人去加载
3. 举例:String.class 进行加载时,他会从下至上顺次委托,直到 Bootstrap ClassLoader 为止,这就保障了最根底的类始终由 Bootstrap ClassLoader 进行加载。如果没有这个机制,咱们就能够当“好人”,自定义加载器去加载多份 String.class 文件

四、如何自定义类加载器和 ClassLoader 源码解析

1. 自定义类加载器只须要定义一个类继承 ClassLoader 即可

public class ykClassLoader extends ClassLoader{
       //1. 如果你想要简略的自定义加载的话则重写 findClass 办法
    //2. 如果你想要毁坏双亲委派机制的话则重写 loadClass 办法
}

2.ClassLoader 外围办法 LoadClass

protected Class<?> loadClass(String name, boolean resolve)
        throws ClassNotFoundException
    {synchronized (getClassLoadingLock(name)) {
            // 1. 从缓存里查看是否已加载
            Class<?> c = findLoadedClass(name);
            if (c == null) {long t0 = System.nanoTime();
                try {
                    // 2. 判断父加载器是否为 null,并进行对应的解决
                    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
                }
                // 3. 如果后面的都没有找到,则调用 findClass 办法进行加载
                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);
            }
            return c;
        }
    }
}
退出移动版