$1.1、类加载器生命周期及初始化详解

类的加载是指将class字节码文件加载到虚拟机内存中,总共分为5个阶段:

1、加载

       将字节码文件从外部存储系统(本地磁盘,文件系统,网络)加载到虚拟机内存的过程,这是进入虚拟机的第一步。

2、连接

        连接是整个加载器最耗时的阶段,连接又可以细分为三个阶段:

        2.1、验证:对加载进来的class字节码进行格式,语法等合法性验证

        2.2、准备:对类型的静态变量进行设置默认值,此处是设置默认值(整型为0,布尔为false,实例引用为null),等到使用阶段才真正赋值用户定义的值。

        2.3、解析:将常量池的符号引用替换成直接引用,符号引用:以一组符号描述所引用的目标,可以是形式的字面量,无歧义定位就行。直接引用:指向目标对象的指针。

3、初始化

        对静态变量的赋值语句进行赋值操作

        条件:

        当类首次主动使用时,虚拟机才会对该类型进行初始化操作

        何为主动使用(类的使用可以分为主动使用和被动使用):

        1、创建类的实例对象

        2、调用类的静态成员变量或者给静态变量赋值。

        3、调用类的静态方法

        4、反射,使用Class.forName("com.demo.Test")

        5、启动时,指定main方法所在的类

        6、子类使用时,对应的父类也需要初始化

        7、jdk1.7以后的动态机制(类似于动态代理):Jsp、动态代理

    除了上述7种方式,其它的使用都是被动使用。

1、编译时期的常量(final修饰)
编译时,虚拟机已经将使用该常量的类,把常量值放到了该类的常量池中,因此常量的访问,不会产生定义常量类的初始化动作。
2、运行时期的常量(final修饰)
编译时期不能确定的常量,只能通过运行时期虚拟机进行获取值,因此需要经过类的初始化过程,如果定义了该常量的类还有父类,也相对应的初始化父类。
3、接口的初始化,首先有2个结论
    3.1、子接口的初始化,并不会初始化其父接口,但是父接口可能会被加载进内存,因为加载和初始化是两个不同的步骤。
    3.2、类的初始化,不会初始化其实现的接口。
接口的变量默认就是public、static和final的,所以直接访问编译期的变量时,不会经过接口的初始化动作。
只有当首次主动使用到父接口时,才会对父接口进行初始化。
因此对接口和类的初始化的汇总如下:
A:当子类真正被使用时,子类会被初始化,对应的父类也会被初始化,但是接口除外;对于常量,只有运行期才知道值的常量,类才会需要初始化。
B:针对类而言:对于常量,如果是编译期就定义好了,那么调用变量不会引起类的初始化;运行期间才知道的值常量,则会引起初始化,并且遵循子类等待父类初始化结束的原则。

4、使用

5、卸载

发布了12 篇原创文章 · 获赞 1 · 访问量 377

猜你喜欢

转载自blog.csdn.net/weixin_39800596/article/details/103522399
今日推荐