当程序要使用某个类时,若是该类还未被加载到内存中,则系统会经过加载,链接,初始化三步来实现这个类进行初始化。java
1. 加载安全
加载,是指Java虚拟机查找字节流(查找.class文件),而且根据字节流建立java.lang.Class对象的过程。这个过程,将类的.class文件中的二进制数据读入内存,放在运行时区域的方法区内。而后在堆中建立java.lang.Class对象,用来封装类在方法区的数据结构。数据结构
类加载阶段:学习
(1)Java虚拟机将.class文件读入内存,并为之建立一个Class对象。.net
(2)任何类被使用时系统都会为其建立一个且仅有一个Class对象。指针
(3)这个Class对象描述了这个类建立出来的对象的全部信息,好比有哪些构造方法,都有哪些成员方法,都有哪些成员变量等。对象
Student类加载过程图示:blog
2. 连接生命周期
连接包括验证、准备以及解析三个阶段。内存
(1)验证阶段。主要的目的是确保被加载的类(.class文件的字节流)知足Java虚拟机规范,不会形成安全错误。
(2)准备阶段。负责为类的静态成员分配内存,并设置默认初始值。
(3)解析阶段。将类的二进制数据中的符号引用替换为直接引用。
说明:
符号引用。即一个字符串,可是这个字符串给出了一些可以惟一性识别一个方法,一个变量,一个类的相关信息。
直接引用。能够理解为一个内存地址,或者一个偏移量。好比类方法,类变量的直接引用是指向方法区的指针;而实例方法,实例变量的直接引用则是从实例的头指针开始算起到这个实例变量位置的偏移量。
举个例子来讲,如今调用方法hello(),这个方法的地址是0xaabbccdd,那么hello就是符号引用,0xaabbccdd就是直接引用。
在解析阶段,虚拟机会把全部的类名,方法名,字段名这些符号引用替换为具体的内存地址或偏移量,也就是直接引用。
3. 初始化
初始化,则是为标记为常量值的字段赋值的过程。换句话说,只对static修饰的变量或语句块进行初始化。
若是初始化一个类的时候,其父类还没有初始化,则优先初始化其父类。
若是同时包含多个静态变量和静态代码块,则按照自上而下的顺序依次执行。
4. 小结
类加载过程只是一个类生命周期的一部分,在其前,有编译的过程,只有对源代码编译以后,才能得到可以被虚拟机加载的字节码文件;在其后还有具体的类使用过程,当使用完成以后,还会在方法区垃圾回收的过程当中进行卸载(垃圾回收)。
5. 附录
常见问题:在本身的项目里新建一个java.lang包,里面新建了一个String类,能代替系统String吗?
不能,由于根据类加载的双亲委派机制,会将请求转发给父类加载器,父类加载器发现冲突了String就不会加载了。
6. 参考
【1】 周志明. 深刻理解Java虚拟机:JVM高级特性与最佳实践(第二版)【M】.北京:机械工业出版社,2013
【2】爱飞翔,周志明(译).Java虚拟机规范(Java SE 8版)【M】.北京:机械工业出版社,2015.
【3】https://blog.csdn.net/ln152315/article/details/79223441
【4】https://blog.csdn.net/sinat_38259539/article/details/71794617