Please enable JavaScript.
Coggle requires JavaScript to display documents.
类加载, 类加载器, 双亲委派,每次都调用其父类加载,父加载器不能加载自己再加载
使得JAVA中的类具有层级关系,比如Object只会委托给顶层…
类加载
加载
验证
准备
解析
初始化
-
- 调用
<clinit>()
方法初始化类变量,static{} 代码块
- 如有父类且未初始化需要先初始化
- clinit 方法需要加锁同步阻塞执行防止多次初始化
- clinit 对接口不是必须的如接口有需要初始化变量则生成该方法
- 将验证完的符号引用解析为直接引用
- 除了invokeDynamic 虚拟机会对第一次解析结果缓存
- invokeDynamic 的解析结果不会对其他生效
- 类接口解析:找到类,加载类,判断是否有权限
- 字段解析:递归向上找父类的字段,找到判断有无权限
- 在类中查找有无方法,没有向上查找父类有无方法,没有在抽象类或接口查找若有报错为是抽象方法,是否有权限
- 接口方法解析: 查找接口若是类报错,否则递归向上查找对应方法
- 初始化类变量即静态变量,类变量jdk8 之后放在堆中,之前放在方法区永久代
- 变量只会初始化为0
- 如果具有final属性会执行初始化为其设定值
-
- 是否有父类,是否继承了final类
- 不是抽象类的话是不是实现了所有接口方法
- 类中的字段是否与父类发生矛盾
- 分析数据流和控制流
- 类型转换是否正确
- 跳转是否正确
-
- 是不是能找到类中引用的相应类,方法,字段 有没权限访问
- 确保解析的正常进行
- 通过-Xverify:none 来禁用 提交类加载速度
加载时机
主动引用初始化
- new 对象时候如果没有加载类则执行加载
- 静态方法或者变量调用
- 反射调用
- 类有父类且父类未初始化
- Main类虚拟机启动时
- JDK 动态代理
- 接口定义了default方法需要在实现类之前初始化
被动引用不初始化
- 子类引用父类static变量 子类不初始化,但是会加载
- 通过数组定义的引用类
- 调用被final修饰的常量时
加载过程
- 读取二进制流,可以是文件也可以是网络流压缩包等
- 在方法区生成类的运行时数据结构
- 在内存中生成一个java.lang.Class 对象 作为方法区参数的入口
- 可通过loadClass方法自定义类加载器,控制字节流获取方式
- 数组类本身不通过类加载器加载,虚拟机直接在内存中动态构建,但是元素类型的类还是需要类加载器加载
类加载器
BootStrap ClassLoader
-
- 加载JAVA_HOME/lib下的类
- -XbootClassPath指定的路径中的类
- 双亲委派,每次都调用其父类加载,父加载器不能加载自己再加载
- 使得JAVA中的类具有层级关系,比如Object只会委托给顶层引导类加载器
破坏双亲委派:
- JNDI的调用,在线程上下文中设置一个类加载器,默认从父线程继承,如果全局范围没有设置则使用App ClassLoader
- 热替换热部署OSGI