乐趣区

关于java:类加载器机制

类加载机制

类加载器品种:

  • 启动类加载器
  • 扩大类加载器
  • 零碎类加载器

启动类加载器和扩大类加载器没有父类加载器,而零碎类加载器的父类加载器是扩大类加载器,自定义类加载器父类加载器则是扩大类加载器

所谓的类加载:就是创立.class 文件对应的 class 对象,并将 class 文件加载到内存的过程。

类加载过程次要分为三步:

1、加载:查找类的.class 文件,并创立 class 对象

2、链接:分三小步:

  • 验证:验证 class 文件中信息是否合乎虚拟机要求;
  • 筹备:动态变量分配内存和设置初始化值,不包含 final 润饰的动态变量,final 变量在编译的时候就会初始化、也不包含实例变量,动态变量即类变量,会调配在办法区中,而实例变量随对象一起调配到堆中;
  • 解析:将常量池中的符号援用替换为间接援用,即替换为间接指向指标的指针、绝对偏移量或一个间接定位到指标的句柄;

3、初始化:若有父类,初始化父类,执行动态初始化器、动态变量(筹备阶段只是赋予了默认值)、以及成原变量初始化。

 ClassLoader 源码剖析

loadClass办法用于加载 class 文件,这里类加载机制设波及到双亲委派机制。

双亲委派机制:即子类加载器收到类加载申请时,会提交给父类加载器解决,如果父类加载器下面还有父类加载器,则持续递归,找到最终的父类加载器加载,当父类加载器加载类失败时,才会由子类加载器中的 findClass() 办法去加载。

双亲委派机制的目标是:

1、这种带有优先级的档次关系,能够防止类被反复加载,当父类加载器加载过,子类就不必加载;

2、保障类加载的安全性:比方外围的 Api 库被篡改,父类加载器加载,会间接报错。

protected Class<?> loadClass(String name, boolean resolve) throws ClassNotFoundException
 {synchronized (getClassLoadingLock(name)) {
    // 首先查寻该类是否曾经被加载
    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) {//c==null 阐明父类 / 启动类加载器未找到该 class,此时调用 findClass()办法
            long t1 = System.nanoTime();
            // 此 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) { // 是否解析该类,调用的是 native 办法
            resolveClass(c);
      }
       return c;
    }
 }
退出移动版