class文件存放在磁盘上,需要的时候,JVM会将他们加载到内存上,进行验证,转换解析,初始化最终形成Java类型可以直接被JVM使用。
Java的类的加载,连接,初始化是在程序运行过程中进行的,并没有预处理,这虽然让内存会耗费一些资源,但是可以说上是遇水架桥,逢山开路,更加灵活。
class类加载到内存上,一直到从内存上卸载掉,一共七个步骤。
01.加载 02.验证 03.准备 04.解析 05.初始化 06.使用
07.卸载
其中,加载,验证,准备,初始化,卸载的前后顺序都是固定的,解析和使用就不是这样了。
先开始说第四步,初始化 。这个时候加载,验证,准备都已经开始了
遇到什么情况下,JVM会去初始化class文件呢?
01.new,getstatic,putstatic,invokestatic,这四个字节码指令的时候
02.调用java.lang.reflect,完成java反射的时候。
03.初始化的时候,父类没有初始化,需要先去触发父类初始化
04.虚拟机启动的时候,需要找到程序的入口(main方法),初始化这个入口所在的class类文件。
05.jdk1.7和jdk1.8的各一个特性。
加载:
类加载的第一个阶段加载,需要在这个期间完成三件事情:
01.通过类的全限定名去获取这个类的二进制流文件。
02.将这个字节流代表的静态存储结构转化为方法区运行时的数据结构
03.在内存中生成一个这个类的java.lang.class对象,作为方法区这个类各种数据的访问入口。
ps:java.lang.class类是用来记录各种类记录的类
因为严格规定这个二进制流必须从class文件上获取,所以也可以从其他地方获取,例如zip文件(发展出了日后的jar,war文件),jsp文件(jsp文件生成对应的class文件)等等。
验证:
想到这个,就想起网络中的海明码验证。有,那是字节码验证。
验证分成四个阶段:
01.文件验证 主要检验class文件的格式是否正确
02.元数据验证 就好像是HTML语言中,用来描述数据的数据,在class文件中,就是那好似那,class文件中的字段表等,验证的点包括01是否有父类02.是不是被final修饰03.是不是抽象类
03.字节码验证
04.符号引用验证
准备:
正式将类中的定义的变量分配到内存中
解析:
初始化:
最后也是最重要的部分,在这个部分,JVM才开始执行class中的java代码,主导权也从JVM变成Java应用程序