首页 > 解决方案 > jvm什么时候加载instanceof操作符的导入类?

问题描述

假设我有两个班级 A 和 B。

class A{}

import A;
class B{}

那么如果在某个对象上我在main方法中做if(object instanceof B),它会加载类A以及它在类的导入语句中B吗?类加载器究竟何时会在运行时加载这些类?

标签: java

解决方案


有两点需要注意:

  1. import语句不会影响类的运行时行为。不会为 import 语句生成任何代码。而如果你只是在B类中导入A类,那么加载B类不会导致A类被加载。

  2. 类加载时间和类初始化时间不同。

类的生命周期是在使用之前加载、链接和初始化(参见JLS 第 12 章)。

  • 加载由类加载器执行,包括定位类文件、将其读入 abyte[]并调用ClassLoader::defineClass.

  • 链接由 JVM 核心代码执行,包括符号引用的验证、准备和解析。JLS 12.3是这样说的:

    该规范允许在何时发生链接活动(以及由于递归,加载)时实现灵活性,前提是尊重 Java 编程语言的语义,在初始化之前对类或接口进行完全验证和准备,并且在链接期间检测到的错误会在程序中的某个点被抛出,在该点上,程序采取了一些可能需要链接到错误中涉及的类或接口的操作。

    这意味着我们无法具体说明何时执行不同的任务。

  • 在链接所有相关类之后进行初始化。根据JLS 12.4.1

    类或接口类型 T 将在以下任何一项第一次出现之前立即初始化:

    • T 是一个类,并创建了一个 T 的实例。
    • 调用由 T 声明的静态方法。
    • 分配了一个由 T 声明的静态字段。
    • 使用了由 T 声明的静态字段,并且该字段不是常量变量(第 4.12.4 节)。

根据 JLS(见上文),我们无法准确说明何时B加载和链接。我们只能说它发生在B初始化之前......如果它被初始化。(您可以通过打开一些 JVM 日志来了解类加载的顺序。但是,顺序可能会因 JVM 供应商和版本而异。)

根据 JLS(见上文),当您的方法创建B第一个实例时(通常)会发生初始化。假设在您的 Question 中已经初始化为一个实例,则初始化将在测试之前发生。如果不是,则不会被测试初始化​​。BmainobjectBinstanceofBinstanceof

从表面上看,不需要A加载类。(这取决于 class 是否以及如何B实际使用 class A,以及代码库的其他部分是否/如何使用A。)


推荐阅读