一、什么是类的加载?
答: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; } }}