Java中类加载的过程
类加载过程
这里的加载过程是严格按照加载开始顺序进行的,注意是加载开始而不是加载完成。也就是有可能会有两个或几个阶段是同时进行的。
比如下面提到的验证过程中的符号引用验证是在解析阶段开始之后进行。
加载(loading):
(1)、通过一个类的全限定名来获取定义此类的二进制字节流。
(2)、将这个字节流所代表的静态存储结构转化为方法去运行时数据结构。
(3)、在内存中生成一个代表这个类的java.lang.Class对象,作为方法区这个类各种数据的访问入口
连接(linking):
1、验证(verification):
(1)、文件格式验证。是否以魔术0xCAFEBABE开头、检查常量池tag标志等。
(2)、元数据验证。对字节码描述的信息进行语义分析。例如验证这个类是否有父类、在这个类的父类是否继承了不允许被继承的类(被final修饰的类)。
(3)、字节码验证:主要确定程序语义是否合法,符合逻辑的。再元数据验证后就要对类的方法体进行验证。比如保证方法体中的类型转化总是有效的。
(4)、符号引用验证:这个发生连接的第三阶段解析阶段将符号引用转化为直接引用的时候。验证该类是否缺少或者被禁止访问它依赖的某些外部类、方法、字段等资源。
2、准备(preparation):
准备阶段是正式为类中定义的变量(即静态变量)分配内存并设置类变量初始值的阶段。jdk8之后,类变量会随着Class对象一起存放在Java堆中。这里进行内存分配的仅包括类变量,而不包括实例变量,实例变量将会在对象实例化时一起分配在Java堆中。并且这里所说的初始值一般都是这个数据类型的零值。但是如果是static final定义变量就会设置为它所指定的值。
3、解析(resolution):
解析阶段是Java虚拟机将常量池内的符号引用替换为直接引用的过程。
初始化(initializing)
在准备阶段变量已经赋过一次初始零值,而在初始化阶段则会根据程序员程序编码制定的主观计划去初始化类变量和其他资源