Java类初始化条件java
(1)类加载的时机:数组
a) 生命周期:加载,验证,准备,解析,初始化,使用,卸载。数据结构
b) 5个肯定的加载顺序,验证,准备,初始化,卸载。函数
c) 初始化的条件(有且仅有的四个条件):对象
i. 遇到new,getstatic,putstatic,invokestatic字节码时,若未初始化,触发。继承
ii. 反射调用的时候,若没有初始化,触发;递归
iii. 初始化类时,若父类未初始化,触发;接口
iv. 虚拟机启动是,主类(含有main方法)触发初始化;生命周期
要点:内存
(1)子类中调用父类的静态字段,只会触发父类的初始化,不会触发子类的初始化;
(2)New一个类的数组的时候,不会触发类的初始化阶段;
(3)类调用static final常量,不会触发类的初始化。
特列:
接口的初始化和类的初始化稍有不一样,接口中没有static代码块。区别在于类初始化条件第三条的父类初始化,如果接口则不须要初始化接口的时候初始化父类接口,只有当引用父类的时候才会进行初始化。
Java类加载过程
(1)加载:
a) 根据类的权限定名获取二进制字节流;
b) 将上述动做获取的字节流中表明的静态存储结果转化为运行是数据结构;
c) 在java堆中生成一个class对象,做为数据访问入口。
(2)验证(确认字节流信息符合虚拟机要求):
a) 文件格式验证:确保获取的二进制字节流可以正确解析,并存储于方法区中;
b) 元数据验证:进行语义分析,确保符合java语言规范;
c) 字节码验证:主要进行数据流和控制流分析;
d) 符号引用验证:确保解析阶段正常运行,若没法经过验证,抛出异常。
(3)准备(正式为变量分配内存并设置类变量初始值的阶段)
初始化的部分只是变量,一般状况下都为零值。
若是具备final修饰,则初始化为指定的值。
(4)解析
将常量池里面的符号引用转化为直接引用的过程
a) 类或者接口的解析:
i. 若不是数组类型,传递全限定名给当前类的加载器;
ii. 如果数组类型,而且为对象元素,相似Integer类,则按照第一点加载元素类型,如果integer类,直接生成维度堆
iii. 上述步骤没有异常,则进行符号引用验证,确认访问权限。
b) 字段解析:
ⅰ. 自己具备简单名和字段描述都与目标相匹配的字段,则返回;
ⅱ.不然,如果有接口实现,从上往下递归搜索,找到则返回;
ⅲ.不然,按照继承关系,从上往下递归搜索,找到则返回;不然抛出异常;
c) 类方法解析
和字段解释稍微有点不一样的地方是,找方法时先找父类,而不是接口。其余逻辑就是找到匹配的则返回。这里要判断自己是否为抽象类,由于匹配到的方法多是实现的接口列表以及父接口的方法;不然NOsuchmethod异常
d) 接口方法解析
与类方法的过程是同样的。区别就是不须要断定是否是实现过该方法。
(5)初始化
这个阶段是开始执行java代码的时候。这个阶段是执行构造函数的过程。
Java类加载器
Java里面的三类加载器:启动类加载器,扩展类加载器,应用程序类加载器。推荐使用的双亲委派模型。每一次的加载都要求先把这个加载请求发到父类加载器进行加载,全部的加载请求最终都会传给启动类加载器,只有当父类加载器反馈回来不能完成加载请求,则尝试本身加载。
OSGI 则是破坏双亲委派模型的案例之一。