• 『JVM』类加载过程


    类加载主要有三个过程:loading 、linking 、initializing

    其中linking又分为三个步骤:verification 、preparation 、resolution

    1:loading是把一个class文件加载到内存中

    2:接下来就是Linking,分为三小步

      2.1:verification 用来校验加载进来的class文件是否符合class文件标准,如果不符合直接拒绝

      2.2:preparation 将class文件的静态变量赋默认值而不是初始值,如 static int i = 8;这个步骤并不是将 i 赋值为8,而是赋值默认值0

      2.3:resolution 把class文件常量池中用到的符号引用转换成内存地址,可以访问到的内容

    3:initialzing 成为初始化,静态变量这个时候才会被赋值为初始值

    下面为loading的过程图

    类加载器的加载过程是分成不同的层次来加载的,不同的类加载器加载不同的class文件,Bootstrap > Extension > App > Custom(自定义类加载器)

    1:第一个类加载器:Bootstrap 称为启动类加载器,是Java类加载层次中最顶层的类加载器,负责加载JDK中的核心类库

    2:第二个类加载器:Extension 是用来加载扩展类的,主要加载Java的扩展类库,默认加载JAVA_HOME/jre/lib/ext/目录下的所有jar包

    3:第三个类加载器:Application 称为系统类加载器,负责在JVM启动时,加载来自Java中的classpath或者java.class.path系统属性或者

               CLASSPATH操作系统属性所指定的jar类包和类路径

    4:第四个类加载器:CustomClassLoader(自定义加载器)

    文字描述:

    用比较通俗的话来解释loading这个过程,当有一个类需要被加载时,首先要判断这个类是否已经被加载到内存,判断加载与否的过程是有顺序的,

    如果有自己定义的类加载器,会先到custom class loader 的cache(缓存)中去找是否已经加载,若已加载直接返回结果,

    否则到App的cache中查找,如果已经存在直接返回,如果不存在,到Extension中查找,存在直接返回,

    不存在继续向父加载器中寻找直到Bootstrap顶层,如果依然没找到,那就是没有加载器加载过这个类,需要委派对应的加载器来加载,

    先看看这个类是否在自己的加载范围内,如果是直接加载返回结果,若不是继续向下委派,以此类推直到最下级,

    如果最终也没能加载,就会直接抛异常 ClassNotFoundException,这就是双亲委派模式。

      public static void main(String[] args) {
    System.out.println(
    "----------------Bootstrap加载类----------------"); String property = System.getProperty("sun.boot.class.path"); String s = property.replaceAll(";", System.lineSeparator()); System.out.println(s); System.out.println("-------------------Ext加载类-------------------"); String property1 = System.getProperty("java.ext.dirs"); String s1 = property1.replaceAll(";", System.lineSeparator()); System.out.println(s1); System.out.println("-------------------App加载类-------------------"); String property2 = System.getProperty("java.class.path"); String s2 = property2.replaceAll(";", System.lineSeparator()); System.out.println(s2); }

    ----------------Bootstrap加载类----------------
    C:Program FilesJavajdk1.8.0_201jrelib esources.jar
    C:Program FilesJavajdk1.8.0_201jrelib t.jar
    C:Program FilesJavajdk1.8.0_201jrelibsunrsasign.jar
    C:Program FilesJavajdk1.8.0_201jrelibjsse.jar
    C:Program FilesJavajdk1.8.0_201jrelibjce.jar
    C:Program FilesJavajdk1.8.0_201jrelibcharsets.jar
    C:Program FilesJavajdk1.8.0_201jrelibjfr.jar
    C:Program FilesJavajdk1.8.0_201jreclasses


    -------------------Ext加载类-------------------
    C:Program FilesJavajdk1.8.0_201jrelibext
    C:WindowsSunJavalibext


    -------------------App加载类-------------------
    C:Program FilesJavajdk1.8.0_201jrelibcharsets.jar
    C:Program FilesJavajdk1.8.0_201jrelibdeploy.jar
    C:Program FilesJavajdk1.8.0_201jrelibextaccess-bridge-64.jar
    C:Program FilesJavajdk1.8.0_201jrelibextcldrdata.jar
    C:Program FilesJavajdk1.8.0_201jrelibextdnsns.jar
    C:Program FilesJavajdk1.8.0_201jrelibextjaccess.jar
    C:Program FilesJavajdk1.8.0_201jrelibextjfxrt.jar
    C:Program FilesJavajdk1.8.0_201jrelibextlocaledata.jar
    C:Program FilesJavajdk1.8.0_201jrelibext ashorn.jar
    C:Program FilesJavajdk1.8.0_201jrelibextsunec.jar
    C:Program FilesJavajdk1.8.0_201jrelibextsunjce_provider.jar
    C:Program FilesJavajdk1.8.0_201jrelibextsunmscapi.jar
    C:Program FilesJavajdk1.8.0_201jrelibextsunpkcs11.jar
    C:Program FilesJavajdk1.8.0_201jrelibextzipfs.jar
    C:Program FilesJavajdk1.8.0_201jrelibjavaws.jar
    C:Program FilesJavajdk1.8.0_201jrelibjce.jar
    C:Program FilesJavajdk1.8.0_201jrelibjfr.jar
    C:Program FilesJavajdk1.8.0_201jrelibjfxswt.jar
    C:Program FilesJavajdk1.8.0_201jrelibjsse.jar
    C:Program FilesJavajdk1.8.0_201jrelibmanagement-agent.jar
    C:Program FilesJavajdk1.8.0_201jrelibplugin.jar
    C:Program FilesJavajdk1.8.0_201jrelib esources.jar
    C:Program FilesJavajdk1.8.0_201jrelib t.jar
    E:ProjectJavaoutproductionJava
    D:IntelliJ IDEAIntelliJ IDEA 2019.2.4libidea_rt.jar

    为什么要搞双亲委派?

    主要是为了安全,这里可以使用反证法,如果任何加载器都可以把Class加载到内存中,我们就可以自定义加载器来加载java.lang.string,在打包时可以把密码存为String对象,这样会造成安全问题

    如何打破双亲委派?

    重写loadclass方法

    自定义加载器

    我们自定义的类加载器只需要继承ClassLoader,并覆盖findClass方法

  • 相关阅读:
    UI进阶--控制器View的创建流程以及生命周期方法
    UI进阶--程序启动原理和UIApplication
    UI进阶--常见的项目文件介绍
    浅析 KVO 内部实现
    浅析 Get 和 Post 的区别
    C++实现进制转换
    UIBlurEffect 毛玻璃特效实现
    UITableView左滑显示选择
    排序算法(OC实现)
    valid Palindrome -- leetcode
  • 原文地址:https://www.cnblogs.com/yan-sh/p/13418742.html
Copyright © 2020-2023  润新知