java 接口初始化_再谈 Java 类加载、链接、初始化流程细节问题

问:请依据自己的理解重点谈谈你对 Java 类加载、链接、初始化的理解?

答:一个 Java 类从字节码到能在 JVM 中被使用需要经过加载、链接和初始化三个步骤,而从细节上来说又可以分为五个步骤,分别是加载、验证、准备、解析、初始化。

640?wx_fmt=png&tp=webp&wxfrom=5&wx_lazy=1&wx_co=1

对我们写代码来说,直接可见的是 Java 类加载(使用 ClassLoader)步骤,而链接和初始化是在使用 Java 类之前的流程。

加载是由 ClassLoader 来完成的,ClassLoader 的主要作用是将 Java 字节码转换成 JVM 中的 java.lang.Class 类对象,其次通过双亲委派模式保证了类加载的唯一性和安全性;但是由于双亲委派的存在,所以启动一个类加载过程的类加载器和最终定义这个类的类加载器可能并不是一个(前者称为初始类加载器,后者称为定义类加载器),故一个 Java 类的定义类加载器是该类所导入的其它 Java 类的初始类加载器(譬如 A、B 两个类均未加载,A 中定义了 B 类型的成员,则 A 的定义类加载器会负责启动 B 的加载过程),这个一定要理解。此外 JVM 判断两个 java.lang.Class 是否相同不仅要依据类的全路径描述符,还要保证是同一个 ClassLoader 加载。关于 ClassLoader 相关问题可以查看历史推送。

链接是将 Java 类的二进制代码合并到 JVM 运行状态中的过程,链接依赖于成功的加载流程,链接包括验证、准备和解析等几个步骤。

验证过程是确保 Java 类二进制结构字节码的正确性,如果验证过程出现错误则会抛出 java.lang.VerifyError 错误。

准备过程将创建 Java 类的静态域,同时将这些域的值设为默认值,准备过程不会执行代码(不会执行,不会执行,重要的事情说三遍)。

解析过程确保类的继承、组合等关联类、接口能被正确找到,解析的过程可能会导致其它的 Java 类被加载(譬如在一个 Java 类中会包含对其它类或接口的引用或继承,解析就是去确认这些被引用的类能被正确的找到)。不同 JVM 解析策略可能不同,有些是在链接的时候就递归对所有依赖进行解析,有些只会在真正用到时时才进行解析(譬如只在方法中使用到了其他类)。

初始化是指一个类第一次被使用时 JVM 会进行该类的初始化操作,初始化过程主要是执行类里面的静态代码块和初始化静态域。在一个类被初始化之前,它的直接父类也需要被初始化。但是一个接口的初始化不会引起其父接口的初始化。在初始化的时候,会按照源代码中从上到下的顺序依次执行静态代码块或初始化静态域。

Java 类和接口的初始化过程只会在特定时机发生,具体如下:创建一个未被使用过的 Java 类实例。

调用一个未被使用过的 Java 类静态方法。

给一个未被使用过的 Java 类或接口中声明的静态域赋值。

访问一个未被使用过的 Java 类或接口中声明的静态域且该域不是常值变量。

此外再补充一句,一定搞清类加载初始化流程与类实例化流程的区别,这是两个东西,只有在某些情况下(譬如 new 一个初次使用的对象实例等)这两者才会有直接关联,而关联关系也是先有类家在初始化流程,完事才有类实例化流程。

  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值