什么是类加载机制
把Class文件加载到内存中,并对数据进行校验、转换解析和初始化,最终形成可以被虚拟机直接使用的java 类型就是类的加载机制。
类加载的时机
下图是类在jvm中的生命周期:
何时加载:
- 遇到new/getstatic/putstatic/invokestatic
- 反射
- 子类加载时若父类没有加载,则先加载父类
- 包含main方法的类
- JDK1.7动态语言支持时MethodHandle实例解析后结果REF_getStatic、REF_putStatic、REF_invokeStatic的方法句柄对应的类没有初始化
除了以上5中情况必须加载类,其他情况有具体的jvm实现来决定
class 装载验证流程
加载
加载时类加载的一个过程,包括三件事情:
- 通过类的额全限定名获取类的二进制字节流
- 将字节流的静态存储结构转为运行时方法区数据结构
- 在堆中生成一个代表这个类的java.lang.Class对象,作为方法区数据的访问入口
连接
验证
验证时为了保证JVM的安全,主要有四个阶段的验证:
- 文件格式验证;魔数,版本号等
- 元数据验证;是否有父类,抽象类,final等约束
- 字节码验证;确保执行正确
- 符号引用验证;类方法字段等是否符合规范,是否可以访问等
准备
准备是为类变量分配内存并设置类变量初始值的阶段,这些内存都在方法区中进行分配。
先给类变量分配内存,如public static int value=1;准备阶段过后初始值为0不是1;
通常情况下初始值是0
解析
将常量池中的符号引用替换为直接引用的过程叫做解析。这解析过程又可以分为:类或接口的解析、字段、方法、接口解析。
初始化
初始化阶段是执行类构造器<clinit>
()方法的过程。
<clinit>()
是由编译期自动收集类中所有类变量的赋值动作和静态语句块自动产生的。
不需要显示的调用<clinit>()
总在子类这个方法执行之前执行父类的<clinit>()
,是线程安全的,可能会产生阻塞。
什么是类装载器ClassLoader
类加载器是用来实现类加载的动作,但是也可以用于判断两个类是否相等,同一个class文件并且是用同一个类加载器加载的才算相等。
双亲委派模型
JVM角度加载器分两类:C++的Bootstrap ClassLoader和其他加载器。
开发角度分三类:启动类加载器、扩展类加载器、应用程序类加载器。
判断类是否加载从低往上判断,加载的时候自顶向下。