jvm什么时候会为instanceof运算符加载导入的类?

时间:2019-03-20 07:53:48

标签: java

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

class A{}

import A;
class B{}

然后,如果在我用main方法if(object instanceof B)处理的某个对象上,它将加载类A以及类B的import语句中吗? 类加载器究竟何时会在运行时加载这些类?

2 个答案:

答案 0 :(得分:5)

有两件事要注意:

  1. import语句不会影响类的运行时行为。不会为import语句生成任何代码。而且,如果您仅将B类中的A类导入,则加载B类不会导致加载A类。

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

类的生命周期是在使用类之前对其进行加载,链接和初始化(请参见JLS Chapter 12)。

  • 加载由类加载器执行,涉及查找类文件,将其读取到byte[]中并调用ClassLoader::defineClass

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

      

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

    这意味着我们无法确定何时执行不同的任务。

  • 所有相关类均已链接之后,才会进行初始化。根据{{​​3}}:

      

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

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

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

根据JLS(请参见上文),B的初始化(通常)是在B方法中创建main的第一个实例时发生的。假设您问题中的object已初始化为B实例,则初始化将在instanceof测试之前进行。如果没有,则B测试不会初始化instanceof

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

答案 1 :(得分:0)

您可以通过以下方式进行测试:

Main.java:

package test;

import test.sub.B;

public class Main {
   public static void main(String args[]) {
      System.out.println("Creating object");
      final B b = new B();
      System.out.println("instanceof check");
      if (b instanceof B) {
         // Do nothing
      }
   }
}

A.java:

package test;

public class A {
   static {
      System.out.println("Class A loaded");
   }
}

B.java:

package test.sub;

import test.A;

public class B {
   A a;

   static {
      System.out.println("Class B loaded");
   }
}

输出:

Creating object
Class B loaded
instanceof check

因此,导入和声明(A a;)都不会加载类。

这符合维基百科的声明:The Java Class Loader [...] dynamically loads Java classes [...]. [...] This loading is typically done "on demand", in that it does not occur until the class is called by the program. [...]

当您将类A a;中的B更改为A a = new A();时,将加载类A