java中的类加载器

类从被加载到内存中开始,到卸载出内存为止。它的生命周期总共七个阶段:
加载—->验证—->准备—->解析—->初始化—->使用—->卸载。

要加载一个类,我们首先必须要找到他的.class文件,那么我们怎么区分.class文件?
SUN公司规定了每个class文件都必须以0xCAFEBABE为标志开头。
这个标志被称为魔数

当我们找到所需要的.class文件之后,我们就要通过类加载器来进行加载。

类加载器:
1,启动类加载器(Bootstrap ClassLoader):

这个类加载器负责将JAVA-HOME\lib目录下的类库加载到虚拟机内存中,用来加载java的核心库。

2,扩展类加载器(Extendsion ClassLoader):
    
这个类加载器负责加载JAVA-HOME\lib\ext目录下的类库,用来加载java的扩展库,

3,应用程序类加载器(Application ClassLoader):

这个类加载器负责加载用户自定义写的类。

4,用户自定义的类加载器
可以根据用户的需求来加载类
类的加载机制–双亲委派机制

所谓双亲委派机制,就是当一个类加载器要加载一个类时,会首先把这个请求传给他的父类加载器,这样直到最顶端的类加载器(没有父类加载器的加载器),如果父类加载器可以完成类加载任务,则父类加载器进行加载;只有父类加载器无法完成此加载任务时,才自己去加载。

类加载器中的loadClass方法就是根据这个双亲委派机制编写的。

protected Class<?> loadClass(String name, boolean resolve)
      throws ClassNotFoundException
  {
      synchronized (getClassLoadingLock(name)) {
          // 先从缓存查找该class对象,找到就不用重新加载
          Class<?> c = findLoadedClass(name);
          if (c == null) {
              long t0 = System.nanoTime();
              try {
                  if (parent != null) {
                      //如果这个类没有被加载过,则由类加载器委托给父类加载器去加载
                      c = parent.loadClass(name, false);
                  } else {
                  //如果没有父类,则委托给Bootstrap加载器去加载
                      c = findBootstrapClassOrNull(name);
                  }
              } catch (ClassNotFoundException e) {
                                }

              if (c == null) {

                    // 如果Bootstrap也无法加载,则通过自定义实现的findClass去查找并加载
                  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;
      }
  }

此外,类中还有findClass和defineClass俩种方法
findClass是一种寻找类的方法
defineClass为类加载器从.class文件加载字节码生成Class对象的方法。
另外,当用户需要编写自己的类加载器时,我们只能修改findClass,如果重写loadClass方法,则会破坏类的双亲委托机制

猜你喜欢

转载自blog.csdn.net/qq_37232304/article/details/80466556