JVM知识体系-01类加载机制

2023-02-09  本文已影响0人  云芈山人

一、思维导图

01类加载机制.png

二、大纲

2.1 类的加载是什么?

2.2 类的生命周期(重要)

2.2.1 类的生命周期图

类的生命周期.png

注意:顺序执行的意思是开始,而不是完成后进行下一步

2.2.2 过程

1. 加载

注意:此阶段可控性最强,可用系统自带类加载器也可自定义类加载器

2. 连接

2.1 验证

四个阶段

注意:重要但不必须,如所引用类经反复验证,可采用-Xverifynone关闭

2.2 准备

为类的静态变量分配内存,并将其初始化默认值

注意:

2.3 解析

把类中的符号引用(一组符号来描述)转化为直接引用(直接指向目标的指针、相对偏移量或一个间接定位到目标的句柄)


直接指针访问对象.png
句柄访问对象.png

3. 初始化

为类的静态变量赋予正确的初始值

设定的两种方式

JVM初始化步骤

类初始化时机

只有当对类的主动使用的时候才会导致类的初始化

4. 使用

5. 卸载

2.2.3 几种情况下会结束生命周期

  1. 执行System.exit()方法
  2. 程序正常执行结束
  3. 程序执行过程中遇到了异常或错误而异常终止
  4. 由于操作系统出现错误而导致Java虚拟机进程终止

2.3 类加载器

1. 几种加载器的层次关系

类加载器层次关系.png

2. 两种角度分类

2.1 JVM角度

启动类加载器
所有其他类加载器

2.2 开发人员角度

启动类加载器
扩展类加载器
应用程序类加载器

3. JVM类加载机制(重要)

2.4 类的加载

有三种方式

  1. 命令行启动应用时候由JVM初始化加载
  2. 通过Class.forName()方法动态加载
  3. 通过ClassLoader.loadClass()方法动态加载

Class.forName()与ClassLoader.loadClass()加载的区别?

2.5 双亲委派模型(重要)

工作流程

若类加载器收到类加载的请求,首先把请求委托父加载器去完成,依次向上,因此所有的类加载请求最终都应该被传递到顶层的启动类加载器中,只有当父加载器在它的搜索范围内没有找到所需的类时(无法加载),子加载器才尝试自己去加载该类

双亲委派机制

  1. 当AppClassLoader加载一个class时,先委派ExtClassLoader加载
  2. 当ExtClassLoader加载一个class时,先委派BootStrapClassLoader去加载
  3. 若BootStrapClassLoader加载失败(JDK\jre\lib无法找到该类),使用ExtClassLoader加载
  4. ExtClassLoader也加载失败(JDK\jre\lib\ext无法找到该类),则由AppClassLoader加载,若还失败则报出异常ClassNotFoundException

源码分析

public Class<?> loadClass(String name)throws ClassNotFoundException {
       return loadClass(name, false);
}

protected synchronized Class<?> loadClass(String name, boolean resolve)throws ClassNotFoundException {
       // 首先判断该类型是否已经被加载
       Class c = findLoadedClass(name);
       if (c == null) {
           //如果没有被加载,就委托给父类加载或者委派给启动类加载器加载
           try {
               if (parent != null) {
                    //如果存在父类加载器,就委派给父类加载器加载
                   c = parent.loadClass(name, false);
               } else {
               //如果不存在父类加载器,就检查是否是由启动类加载器加载的类,
              //通过调用本地方法native Class findBootstrapClass(String name)
                   c = findBootstrapClass0(name);
               }
           } catch (ClassNotFoundException e) {
            // 如果父类加载器和启动类加载器都不能完成加载任务,才调用自身的加载功能
               c = findClass(name);
           }
       }
       if (resolve) {
           resolveClass(c);
       }
       return c;
   }

意义

JDK1.9后的委派模型

JDK9后的类加载器委派关系.png

2.6 自定义类加载器

一般情况,由三种类加载器互相配合进行加载,如有必要,也可加入自定义类加载器
因JVM自带ClassLoader只懂从本地文件加载标准java cass文件,若编写自己的ClassLoader,需做到以下三点
  1. 执行非置信代码之前,自动验证数字签名
  2. 动态地创建符合用户特定需要的定制化构建类
  3. 从特定的场所所取得java class,如从数据库中和网络中
上一篇 下一篇

猜你喜欢

热点阅读