java类加载机制

类加载总共分为以下几步:1、加载(loading);2、验证(verification);3、准备(preparation);4、解析(resolution);5、初始化(initialization);6、使用(using);7、卸载(unloading)

其中2/3/4步统称为连接(linking)。

加载阶段和连接阶段的部分内容是交叉进行的,有可能加载阶段尚未完成,连接阶段就已经开始。但这些连接阶段混杂在加载阶段的内容仍然属于连接阶段。

加载、验证、准备、初始化、卸载这几个阶段会严格按顺序执行,解析可能在初始化之前也可能在初始化之后,这主要是为了支持java的运行时绑定(也称动态绑定或晚期绑定)。

在执对加载这一步的时候,ClassLoader首先会调用父类的loadClass方法,层层网上,直到没有父类。

通过阅读ClassLoader类的源码可以看到,每个ClassLoader都持有一个对父类构造器的引用parent,当loadclass被调用的时候,会首先检查parent引用是否为null,不为null则直接调用parent.loadclass。

protected Class<?> loadClass(String name, boolean resolve) throws ClassNotFoundException {
        synchronized (getClassLoadingLock(name)) {
            /**
             * Omit a part of code.
             */
            try {
                if (parent != null) {
                    c = parent.loadClass(name, false);
                } else {
                    c = findBootstrapClassOrNull(name);
                }
            } catch (ClassNotFoundException e) {
                // ClassNotFoundException thrown if class not found
                // from the non-null parent class loader
            }

            /**
             * Omit a part of code.
             */
            return c;
        }
    }

类加载的顺序为:

父类静态变量/块

子类静态变量/块

父类成员变量/块

子类成员变量/块

父类构造器

子类构造器

*每个静态变量/块的加载顺序取决于其在代码中定义的顺序(成员变量/块同理)

一个有趣的问题:

当类中的一个静态引用指向一个实例对象,这个实例对象会在所有静态变量/块完成初始化之前初始化。

public class StaticTest {
   
    static int b = 112;

    static StaticTest st = new StaticTest();

    static int magicNumber = 666;
}

如该段代码所示,在类加载的过程中,当执行到 static StaticTest st = new StaticTest(); 这一行时,并不会等后续所有的静态变量/块初始化完成再来执行new StaticTest(),而是先执行了new StaticTest(),再执行后面的静态变量初始化。

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值