【JVM虚拟机学习笔记】类加载机制

个人博客 翔仔年轻有力量:【JVM】类加载机制

类加载过程

在这里插入图片描述

在这里插入图片描述

加载Loading

加载阶段(Loading),完成以下三个步骤:

  • 通过一个类的全限定名获取定义此类的二进制字节流
  • 将这个字节流所代表的的静态存储结构转化为方法区的运行时数据(方法区中的数据存储格式由虚拟机自行定义)
  • 在内存中生成一个代表这个类的java.lang.Class对象,作为方法区这个类的各个数据的访问入口,即程序访问方法区中的类型数据的外部接口。

另外,加载阶段使用不同的类加载器完成,而类加载器可以由用户自定义。通过重写类加载器的findClass()方法和loadClass()方法来自定义类加载以控制二进制字节流的获取方式。

连接Linking

连接阶段分为三步,有验证(Verification),准备(Preparation),解析(Resolution)

验证(Verification)
  • 确保Class文件的字节流中包含信息符合虚拟机规范的全部约束要求,保证被加载类的正确性,这些信息运行后不会危害虚拟机自身安全。
  • 主要包括四种验证:
    • 文件格式验证 - 字节流符合Class文件格式规范,且能被当前虚拟机处理
    • 元数据验证 - 对字节码信息进行语义校验,信息符合虚拟机规范要求
    • 字节码验证 - 通过数据流分析和控制流分析,保证类中方法不会危害虚拟机安全
    • 符号引用验证 - 确保解析行为能正常执行,发生在将符号引用转化为直接引用时
准备(Preparation)
  • 为类中定义的变量(指静态变量,static修饰)分配内存并设置类变量初始值
  • 内存分配不包括实例变量以及被final修饰的常量。实例变量在对象实例化时随对象一起分配到java堆中,而final修饰的常量在编译生成字节码文件时就已初始化完毕
解析(Resolution)
  • 将常量池中的符号引用转换为直接引用的过程,(通俗但不规范地说,即本类中存在引用其他类的方法、变量,在class文件中以常量池常量类型存在,需要解析来获取它们的具体信息,将类或接口、字段、方法等加载进虚拟机)
  • 解析动作主要针对类或接口、字段、类方法、接口方法等共7类符号引用进行

初始化initialiazation

初始化阶段就是执行类构造器clinit()方法的过程。即对类变量进行赋值动作以及运行静态代码块。

  • clinit()方法执行有以下特性:
    • 静态代码块只能访问到定义于静态代码块之前的变量
    • 作为类构造器的clinit()方法并非实例构造器init()方法,clinit()方法不需要显式调用父类构造器
    • 子类的clinit()方法执行前,父类的clinit()方法已经执行完毕。但接口的clinit()方法执行前不需要先执行父接口的clinit()方法
    • clinit()方法在多线程环境下会被正确地加锁同步,达成多个线程初始化同一个类时,只有一个线程执行clinit()方法,其他线程阻塞等待,直至clinit()方法执行完毕。
  • 另外初始化阶段,JVM规定以下六种情况必须对类进行初始化:
    • 使用new实例化对象时、对某类的静态字段进行操作时(非final修饰)、调用某类的静态方法时
    • 使用反射调用某个类且该类没有进行初始化时
    • 子类初始化时,父类未初始化则先对父类进行初始化
    • 虚拟机启动时,优先初始化用户指定的主类(含main方法的类)
    • REF四种类型的方法句柄对应的类需先触发初始化
    • 一个类实现的接口中含有被default修饰的默认方法时,该接口优先于该类初始化

类加载器

在加载阶段,通过一个类的全限定名获取定义此类的二进制字节流的动作由类加载器来实现。类加载器包括两种:一种是启动类/引导类加载器(为JVM自身的一部分),另一种是其他所有类加载器(派生于抽象类ClassLoader)。

类的唯一性由加载的类加载器以及类本身共同确立,即两个类“相等”是建立在二者来自同一个Class文件,且被同一个JVM运行,并由同一个类加载器加载的条件下。

双亲委派模型

在这里插入图片描述

  • 要求除了启动类加载器外,其余类加载器都应有自己的父类加载器,且父子关系使用组合形式来复用父加载器的代码而非继承
  • 类加载器收到类加载请求优先委派父加载器去完成,故最终所有加载请求均传送至启动类加载器。当父类加载器反馈无法完成加载时,才由子加载器尝试完成。这样的好处在于类随着类加载器的层级关系同时具备了层次,当加载一个类时,都优先由它对应的类加载器去加载,以保证每一次加载的类为同一个类

自定义类加载器

开发者可以通过自定义类加载器来控制Class字节流的获取方式,以达成隔离加载类、修改类加载方式、拓展加载源、防止源码泄露的目的。

具体实现步骤如下:

在这里插入图片描述

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值