Java虚拟机将class文件中的信息加载到内存的这一过程称为类加载。类加载分为七个阶段, 加载,验证,准备,解析,初始化,使用,卸载。 加载->验证->准备->初始化->卸载,是固定顺序,必定在下一步之前开始,但不一定在下一步之前结束。解析可以在初始化之前开始,也可以在初始化之后开始(这是就是动态绑定,比如接口调用方法) 加载时机根据虚拟机不同,有不同实现,而初始化时机在四种情况下必须执行。 1使用new关键字实例化对象,访问静态成员,方法。 2 反射调用类。 3初始化类,如果父类没初始化,父类需要先初始化。 4虚拟机启动时,指定一个主类(包含main()方法的那个类),虚拟机会初始化这个类。 四种场景的行为称为对一个类进行主动引用,即直接引用到这个类,而不是间接的。下面介绍几种被动引用。例如一个new对象数组,这时里面对象并未初始化,因为虚拟机自动生成一个数组类。除此之外,通过子类调用父类的静态成员,子类也不会初始化。直接引用的是父类。final字段修饰的字段放入常量池中,引用该字段,也不会初始化。因为没有直接引用到该类而是访问常量池。 类加载过程: 第一步加载 通过一个类的全限定名来获取此类的二进制字节流,有很多方式,列常见的几种 可以从zip包读取,如apk,jar,ear。 从网络中获取,如Applet 运行时计算生成,动态代理技术 由其他文件生成,如JSP应用 加载阶段可以用系统的类加载器加载也可以用自定义的类加载器几种。 类加载器分为三种,启动类加载器,扩展类加载器,应用程序类加载器(默认是这个加载器完成类的加载)。类加载器不同,即时从同一个class文件加载出来,isInstance,equal方法也不会相等。 第二步验证: 主要是为了Java虚拟机自身的安全,分为四个验证阶段,文件格式验证,验证class文件是否错误。元数据验证,字节码信息是否符合Java语言规范要求。字节码验证,保证方法体能够调用。符号引用验证,确保符号引用能正常访问。 第三步准备 为类变量(不是对象变量)static成员设置初始化默认值。如果成员被声明为final类型,就会用常量池中的值初始化。 解析 有两种引用,符号引用和直接引用,解析过程就是将符号引用替换成直接引用。符号引用指向的目标不一定在内存中,直接引用一定在内存中。对类,接口,字段,类方法,接口方法四类符号引用进行解析,首先来看类或接口的解析。 如果不是数组类型,类加载器加载类或接口,是数组类型,虚拟机生成一个数组对象。 字段解析 先从本身类查找与简单名称和字段描述符都匹配的字段,没查到再从接口从上往下查找,还没查到最后从类从上往下查。 类方法解析,接口方法也是类似, 初始化 执行类构造器clinit方法,自动收集类变量的赋值动作和静态语句块合并产生的。与实例构造器init不同,不需要显式调用父类构造器,虚拟机保证在子类的clinit执行前父类clinit执行完毕。 |
|
来自: Dragon_chen > 《Java》