JVM中有两种类型的类加载器,由C++编写的及由Java编写的。除了启动类加载器(Bootstrap Class Loader)是由C++编写的,其他都是由Java编写的。由Java编写的类加载器都继承自类java.lang.ClassLoader。各种类加载器之间存在逻辑上的父子关系,后面可以通过代码查看。
public class ClassLoadeTest1 extends ClassLoader{ public static void main(String[] args) throws ClassNotFoundException { ClassLoadeTest1 classLoadeTest1 = new ClassLoadeTest1(); Class<?> aClass = classLoadeTest1.loadClass(Demo1.class.getName()); System.out.println(aClass); System.out.println(aClass.getClassLoader()); } @Override protected Class<?> findClass(String name) throws ClassNotFoundException { System.out.println("findClass"); return null; } } 结果: class com.example.classloade.Demo1 sun.misc.Launcher$AppClassLoader@18b4aac2 因为类加载中的双亲委派 所以打印出的加载类为AppClassLoader 这也是自定义的默认加载器
自定义类加载器也可以打破双亲委派,看源码 此处代码说明类加载器父子关系图
/** * 类加载过程如下 * 自定义加载器只需要重写loadClass 在向上委托判断初改成自己加载逻辑即打破双亲委派 **/ protected Class<?> loadClass(String name, boolean resolve) throws ClassNotFoundException{ synchronized (getClassLoadingLock(name)) { //判断类是否加载过 Class<?> c = findLoadedClass(name); //==null 没有加载 if (c == null) { long t0 = System.nanoTime(); try { //判断是否有父级 (这块逻辑重写 为自己加载 即打破类双亲委派) if (parent != null) { //有父级委托父级加载 向上委派 c = parent.loadClass(name, false); } else { //没有的话直接使用启动类加载器 最后调用的是navicat方法 进入c++ 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); } return c; } }