类加载机制
程序员文章站
2022-04-08 21:34:09
类的生命周期 一个java文件的整个生命周期,总共要经历加载-验证-准备-解析-初始化-使用-卸载这几个阶段,有的人把验证准备解析归纳为一个阶段称为链接,所有有的说5个阶段的,也有说7个阶段的,两种说法。 什么时候开始加载? 1.用new实例化对象的时候。 2.读取或者设置一个类的静态字段的时候。 ......
类加载机制
类加载就是把class文件加载到内存里面,对数据进行校验、转换解析和初始化,形成供JVM直接使用的Java类型的过程。
类加载过程
加载(Loading)
- 通过一个类的全限定名来获定义此类的二进制字节流。
1. Zip压缩包获取,JAR、EAR、WAR
2. 网络获取,Web Applet
3. 运行时计算生成,动态代理
4. 其他文件生成,JSP
5. 数据库中读取
6. 加密文件中获取,防反编译 - 将字节流所代表的静态存储结构转换为方法区的运行时数据结构。
- 在内存中生成一个达标这个类的java.lang.Class对象,作为方法区这个累的 各种数据的访问入口。
验证(Verifation)
- 文件格式验证
- 元数据验证 语义校验
- 字节码验证
- 符号引用验证
准备(Preparation)
准备阶段是正式为类中定义的变量(静态变量)分配内存并设置类变量初始值的阶段。这些内存应该在方法区进行分配。
这里的初始值一般都是零值。
解析(Resolution)
常量池中的符号引用替换为直接引用的过程。
- 符号引用
以一组符号来描述所引用的目标,可以是任意形式的字面量,无歧义即可。与内存布局无关。在Class文件格式中定义过。 - 直接引用
可以直接指向目标的指针、相对偏移量,或者是一个句柄。与内存布局相关。
1. 类或者接口的解析
- 非数组类型符号引用解析,由虚拟机把全限定名传递给引用所在类区加载引用所对应的类或者接口。
- 数组对象引用解析,先加载出元素类型,然后又虚拟机生成一个数组对象。
- 进行引用验证,确认是否具备访问权限,如果不具备,抛出IllegalAccessError异常。
2. 字段解析
- 解析字段所属的类或者接口的符号引用,这里用C来代替这个类或者接口。
- 递归查找,依次在C、C的父接口、C的父类中查找匹配字段,如果没有就抛出NoSuchFielError异常。
- 没有抛出异常,就进行权限验证,如果不具备,抛出IllegalAccessError异常。
3. 方法解析
- 解析方法所属的类或者接口的符号引用,这里用C来代替这个类或者接口。
- 首先验证C不是接口,如果是接口,直接抛出异常;
然后递归查找,依次在C、C的父类中查找匹配的方法,如果在C的父接口中出现匹配,说明是一个抽象类,抛出AbstractMethodError;
最后,如果没有前面都没有匹配上,就抛出NoSuchMethodError异常。 - 没有抛出异常,就进行权限验证,如果不具备,抛出IllegalAccessError异常。
4. 接口方法解析
- 解析方法所属的类或者接口的符号引用,这里用C来代替这个类或者接口。
- 首先验证C不是类,如果是类,直接抛出异常;
然后递归查找,依次在C、C的父接口中查找匹配的方法;
最后,查找失败,抛出NoSuchMethodError异常。 - 没有抛出异常,就进行权限验证,如果不具备,抛出IllegalAccessError异常。
初始化(Initialization)
初始化阶段就是执行类构造器()方法的过程。这时JVM才开始执行类中编写的代码。
()方法是有编译期自动收集类中的所有类变量的赋值动作和静态语句块中的语句合并产生的。
JVM会保证在子类的()方法执行前,父类的()方法已经执行完毕。
接口的()方法不需要先执行父接口的()方法。接口的实现类在初始化时不会执行接口的()方法。
类的()方法在多线程环境中会加锁同步,如果一个类的()方法有耗时很长的操作,就可能造成多个线程阻塞。
使用(Using)
卸载(Unloading)
本文地址:https://blog.csdn.net/zhengkun51/article/details/107675370
上一篇: 每次和闺蜜逛街