JVMAndroid开发Android技术知识

虚拟机的类加载机制

2017-12-19  本文已影响17人  紫霞等了至尊宝五百年

虚拟机把描述类的数据从Class文件加载到内存,并对数据进行校验、转换解析和初始化,最终形成可以被虚拟机直接使用的Java类

即虚拟机的类加载机制.

在Java中,类型的加载、链接和初始化过程都是在程序运行期间完成的

如编写一个面向接口的应用程序,可等到运行时再指定其实际的实现类.
这种策略虽然会令类加载时增加一些性能开销,但是会为Java应用程序提供高度的灵活性.

Java天生的可以动态扩展的语言特性就是依赖运行期动态加载和动态链接

1 类加载的时机

类从被加载至内存到卸载出内存的生命周期

其中加载、验证、准备、初始化和卸载这5个阶段的顺序是确定的.
而解析阶段可能会在初始化阶段后再开始.

虽然上述的5个阶段可能按序,但是并不是说一个接一个阶段完成后才开始,一个阶段的进行完全可能激活另一个阶段的进行,交叉混合式的进行

什么情况下需要开始类加载过程的第一个阶段-加载呢?
并无强制规范,但对于初始化阶段,有且只有以下5种情况必须立即对类进行初始化

这5种行为称为对一个类进行主动引用,此外的所有引用类的方式都不会触发初始化,称为 被动引用


输出结果
初始化父类!
666

但由于这个静态成员变量属于父类,子类只是间接调用父类中的静态字段,因此子类调用value属于间接引用,而父类调用value属于直接引用

对于静态字段,只有直接定义这个字段的类才会被初始化,通过其子类引用父类中定义的静态字段,只会触发父类的初始化!


并没有输出”初始化父类!”

但现在通过new要创建的是一个数组对象,而非SuperClass类对象,因此也属于间接引用,不会初始化SuperClass类



输出结果

hello world

但ConstClass类的静态字段被final修饰,是一个常量
被final修饰的常量在Java代码编译的过程中就会被放入它被引用的class文件的常量池中(这里是NotInitialization的常量池).
所以程序在运行期间如果需要调用这个常量,直接去当前类的常量池中取,而不需要初始化这个类

实际上,NotInitialization的Class文件中并无ConstClass类的符号的入口,这俩类在编译成Class之后就不存在任何联系了

接口和类都需要初始化,接口和类的初始化过程基本一样,有所区别的是前面说的5种情景的第三条

上一篇下一篇

猜你喜欢

热点阅读