类加载过程
加载->链接(验证,准备,解析)->初始化
1.加载:
利用io从文件系统中读取.class文件,通过类加载器(classLoader)进字节码加载到计算机内存中供Jvm使用。
java的四种类加载器(父加载器->子加载器)
1引导类加载器:加载Java 的核心库
2扩展类加载器:加载java 的扩展库
3系统类加载器:加载Java 应用的类路径(CLASSPATH) 自定义的类通过系统类加载器或自定义类加载器加载
4自定义类加载器:开发人员自定义java类加载器
怎么确定使用哪种加载器来加载一个类?
java体系中使用的加载机制是双亲委派模式:
大致流程:加载器如果还有父加载器就将加载交到父加载器加载。
其实真正的加载过程是从1引导类加载器开始加载,加载不了则继续先下加载。
优点:
1.防止一个类重复加载
2.保证java核心API不会被修改
即使外部重新定义了java核心库的类(比如Object),但是仍然会被引导类加载器加载而不是系统类加载器加载。
思考:为什么不直接从引导类加载器开始加载?
2.链接:
2.1.1验证
这里验证的就是后缀名是.class文件,因为我也可以把随便一个其他后缀名(比如.txt .exe)修改成.class文件
验证阶段可以检验是否是合法的class文件,是否有必要加载到内存中
魔数:cafe babe
2.1.2准备
为类中的所有静态变量分配内存空间,并为其设置一个初始值
被final修饰的静态变量,会直接赋予原值
2.1.3解析
所谓解析就是指在常量池(jdk1.8从方法区转移到堆中,方法区更改成元空间)中找到类、接口、方法、字段的符号引用(代码),并将其替换为直接引用(具体指针)的过程。
3.初始化:
这里执行的是cinit方法,不是执行构造函数方法。
执行所有static方法的代码,将准备阶段static变量进行赋值。
补充一点:
加载阶段优先于链接阶段,但是加载的过程,链接阶段也在进行。
是一个并发的过程。
链接过程在加载过程之后结束。
再补充一点:
当一个类在初始化时,要求其父类全部都已经初始化过了
但是在一个接口初始化时,并不要求父接口完全完成了初始化,只有在真正使用到父接口的时候才会初始化(如引用接口中定义的常量。