ClassLoader
2019-07-02 10:55:02 0 举报
AI智能生成
Java类加载器
作者其他创作
大纲/内容
基本概念
:类加载器是 JVM 的运行时核心基础设施模块
类加载器结构
启动类加载器
Bootstrap ClassLoader
Bootstrap ClassLoader
基于 C / C++ 实现
不存在于 JVM 体系,无法获取该 ClassLoader
根基类加载器,负责加载最核心的 JAVA 类,如 Object,System,String 等
扩展类加载器
- Extension ClassLoader
- Platform ClassLoader
加载扩展的系统类,如加密,压缩等相关功能
应用类加载器
Application ClassLoader
Application ClassLoader
加载用户定义的 CLASSPATH 路径下的类
自定义类加载器
- User ClassLoader
- User ClassLoader
类加载过程
加载
1. 通过类的完全限定名,加载定义此类的二进制字节流
2. 将静态存储结构转换为方法区的运行时数据结构
3. 创建该类的 Class 对象,作为方法区中该类各种数据的访问入口
验证
1. 文件格式验证
:该阶段的主要目的
保证输入的字节流能够正确的解析,并存储到方法区之内
验证格式是否符合 JAVA 类型信息的要求
-> 是否以魔法值 0xCAFEBABE 开头
-> 是否能被当前版本的虚拟机处理
-> 检查常量池中的常量,是否有不被支持的类型
-> 是否有被删除或附加一些信息
......
2. 元数据验证
:该阶段的主要目的
对类的元数据信息进行语义校验
确保不存在不符合 JAVA 语言规范的元数据
-> 是否拥有父类
-> 是否继承不允许继承的类(final)
-> 是否出现不符合规则的方法重载
......
3. 字节码验证
:该阶段的主要目的
确保被校验类的方法,不会在运行期间,做出威胁 JVM 的事件
通过数据流和控制流分析,确定语义是否合法并符合逻辑
-> 保证跳转指令不会跳转到方法体以外的字节码指令上
-> 保证类型转换是有效的
......
4. 符号引用验证
:该阶段的主要目的
确保解析动作能够正常执行
-> 验证符号引用中,通过类的完全限定名,是否能够找到对应的类
......
链接
准备
为类变量分配内存并设置初始化值(默认值)
类变量在该阶段仅会初始化为默认值
putstatic 指令存在于 <clinit> 方法,因此赋值操作将在初始化阶段完成
类变量如果为常量,则在准备阶段就会将类变量初始化为指定的值
解析
解析类与方法,确保类与类之间相互引用的正确性
将符号引用替换为直接引用
完成内存结构布局
初始化
执行类构造器 <clinit> 方法
如果赋值运算是通过其它类的静态方法完成的,则立即解析另一个类,在虚拟机栈中执行完毕后通过返回值赋值
由 JVM 保证该方法的线程安全性
双亲委派模型
加载类请求过程
检查当前加载器,是否加载过此类
未加载过,将该请求委派给父加载器,如果父类加载器未加载过,
则继续逐层委派,直到委派到 Bootstrap 加载器
则继续逐层委派,直到委派到 Bootstrap 加载器
如果父加载器无法满足该加载请求
子加载器尝试自行完成该类加载请求
加载过,则直接返回该类的 Class 对象
相关知识点
通过重写 loadClass 方法,可以自定义类加载策略
扩展知识点
热部署技术
热部署技术就是通过破坏双亲委派模型的方式,通过使用不同的 ClassLoader 加载 .class 文件,以达到动态更新的目的
重要知识点
类加载器具有等级制度
等级机制通过组合的方式实现
类加载器遵循组合优先原则
Java 类在 JVM 中的唯一性
类加载器拥有独立的类名称空间
任何一个类,都由类加载器和类本身确定其在 JVM 中的唯一性
不同类加载器加载的类,必不相等
同一个类加载器下的同一个类型只会初始化一次
<clinit> 方法
<clinit> 方法对于类和接口不是必须的,如果没有静态语句块和对类变量赋值的操作,那么编译器不会该类生成 <clinit> 方法
AppClassLoader 和 ExtClassLoader 均为 Launcher 中的静态内部类,具有 default 访问限制
自定义 ClassLoader 的方式
(模版方法模式)重写 findClass 方法,调用 defineClass 方法,将 .class 实例化为 Class 对象
0 条评论
下一页