主要分为三个步骤:装载,链接,初始化
一,装载:查找.class文件生成字节流,再生成class对象。
隐式装载-》写代码时候new的对象,系统就会调用类加载器装载对应class到内存。
显示装载-》写代码时候调用Class.forName()等方法会进行装载操作。
二,链接:又分为3步骤(验证,准备,解析)
1,验证:确保class文件中的字节流包含的信息符合要求,而且不会危及虚拟机安全。
2,准备:为类的静态变量分配内存,并设置初始值是0(一般的java基本数据类型默认值都是0,引用类型默认值都是null),真正的值是在初始化阶段设置的。(不过对于静态常量就是直接在准备阶段就将真正的初始值设置好了)
3,解析:把常量池中的符号引用变为直接引用,常量池中的类,接口名,字段名,方法名等等都会变为具体内存地址。
三,初始化:初始化变量
初始化时机:
1,虚拟机启动,初始化包含main方法的朱类
2,new对象实例
3,访问静态方法或者静态字段,若目标对象没有初始化就进行初始化操作
4,子类初始化时候若父类没有初始化就会触发父类的初始化操作
5,反射时候若类没有初始化操作就会触发初始化操作
6,第一次调用java.lang.invoke.MethodHandle实例的时候需要初始化MethodHandle指向方法所在的类
在初始化阶段只会初始化被static修饰的信息,而没有被static修饰的信息会在实例化对象的时候才执行。
以上6种情况在虚拟机中称为主动引用,其他都是被动引用。被动引用不会触发class的初始化。
在代码中new对象的时候,对象的初始化顺序是
静态变量/静态代码块-》普通代码块-》构造函数
1,父类的 静态变量/静态代码块
2,子类的 静态变量/静态代码块
3,父类的 普通成员变量/普通代码块
4,父类的构造函数
5,子类的 普通成员变量/普通代码块
6,子类的构造函数