加载
预加载
在启动时,首先加载的是JAVA_HOME/lib/下的rt.jar下的.class文件,这个jar包里面的内容是程序运行时
常用到的,像java.lang.*、java.util.、 java.io. 等等,因此随着虚拟机一起加载。
运行时加载
在jvm加载一个class的时候,首先要在内存中找一下是否已经加载到这个类了,如果没有则对其进行加载
在加载的时候主要完成以下三件事
1)通过类的全限定名来获取定义此类的二进制字节流
2)将该字节流中的静态存储结构转化为方法区的运行时数据结构
3)在内存中生成一个代表这个类的java.lang.Class对象,作为方法区这个类的各种数据访问入口
链接
验证
这一阶段的目的是为了确保.class文件的字节流中包含的信息符合当前虚拟机的要求,并且不
会危害虚拟机自身的安全。
主要做了以下几种验证
1.文件格式验证
2.元数据验证
3.字节码验证
4.符号引用验证
准备
正式为类变量分配内存并设置类变量初始值的阶段,这些变量都在方法区中进行分配。
注意:1.此时只对被static关键字修饰了的变量分配内存空间和初始值,实例变量在对象实例化时和对象一起分配在堆中。
2.例如public static int value = 111;这个111在准备阶段并不会被赋值上,是因为在字节码中赋值的语句putstaic是存放于类构造器
特例:ConstantValue属性的作用是通知虚拟机自动为静态变量赋值,只有同时被final和static修饰的字段才有ConstantValue属性,且限于基本类型和String(因为从常量池中只能引用到基本类型和String类型的字面量)。当字段属性表中存在ConstantValue属性,那么在准备阶段就会直接赋值上去,例如用final+static关键字修饰变量
解析
解析阶段是虚拟机将类中的符号引用替换为直接引用的过程。
1.符号引用
类和接口的全限定名
字段的名称和描述符
方法的名称和描述符
2.直接引用
将符号引用直接指向真实的内存地址0x000010
初始化
初始化就是执行
做了以下几件事情
()是怎么生成的
该方法是由编译器自动收集类中的所有类变量的赋值动作和静态语句块(static{ })合并产生的,收集顺序取决于代码编写的顺序,该方法不是必须的,当代码中存在static它才会被生成
父子类
()的执行顺序
接口也是一个类,它会有
吗
接口中不能使用静态语句块的操作,但是有静态变量要赋值的时候也是会有
多线程下
方法的执行情况
虚拟机会自己保证该方法执行的正确性,当多个线程执行时,只有一个线程可以执行该方法,其余线程都将阻塞
&
加载和链接过程的控制全全部交由虚拟机,由于过程只经历一次因此