类加载子系统
类加载过程
.class 通过 JVM 加载到方法区的过程依赖于JVM的类加载器。
类加载的过程:
.class 文件的加载 -> 链接(验证 -> 准备 -> 解析) -> 初始化
.class文件的加载方式
- 通过本地class文件加载
- 运行时生成的class文件:动态代理
- 通过网络的class文件加载
- 通过jar war压缩包形式加载
- 通过加密文件加载
- ...
链接 (验证 准备 解析)
验证:主要是验证class文件的合法性
准备:
- 给static 变量分配空间,并初始化默认值
- 给 final static 变量进行初始化,分配空间在编译时就已经确定了?
解析:将常量池的符号引用转换为直接引用的过程
初始化
初始化阶段会执行 类构造器
类加载器的分类
类加载器分为引导类类加载器和自定义加载器(扩展类加载器,应用类加载器和用户自定义加载器)
引导类加载器是C/C++写的,用途:
- 加载java javax开头的核心类
- 加载扩张类加载器,应用类加载器,并指定他们为父类为bootstrap classloader
扩展类加载器实用类加载jre/lib/ext包下的所有class
其余的类基本都是由应用类加载器实现。
沙箱机制
java中class是按需加载的,用到时才会加载。
当一个class需要被加载时,收到类加载请求的类加载器会看自己是否有父类如果有则向上委托父类加载器去加载。如果父类加载器无法加载此类,再由自己加载。
这样做的好处就是防止核心类被随意篡改。
当一个攻击者自定义了一个类java.lang.String时,系统类加载器会一步一步交给引导类加载器加载,引导类加载器会优先加载rt.jar包中的java.lang.String类。达到保护的目的。
补充
判断两个.class对象相等不相等有两个关键因素
- 这个类的完整类名
- 加载这个类的classloader
换句话说就是同一份class文件被两个不同的类加载器加载了,那么这两个class对象也是不相等的