Class 正在加载和初始化

Class Loading and Initializing

我试图了解加载和初始化 class 时的确切情况。我看到下面两篇文章给出了不同的答案

javarevisited-A Class 在创建 class 的实例时 在 Java 中初始化 使用 new() 关键字或使用 class.forName() 的反射,这可能会在 Java.[ 中抛出 ClassNotFoundException =16=]

Java world-那么 classes 什么时候加载?恰好有两种情况:当新的字节码被执行时(例如,FooClass f = new FooClass();)和当字节码使对 class 的静态引用(例如 System.out)。

因此,当我使用 new 关键字创建 class 的实例时,class 是否已加载或初始化?


关于引用变量加载的另一件事要问:

javarevisited-Class 加载由 Class 加载器在 Java 中完成,可以实现急切加载 class一旦另一个 class 引用 它或延迟加载 class 直到需要 class 初始化发生

作者在这里引用是什么意思?他是否暗示如果 A class 具有 B class 的引用变量,那么当在 A 中遇到其引用时 B class 会被加载?

但是下面的作者说 class NotUsed 没有加载但是我看到 ClassInitializationTest class 有它的 reference

javarevisited-

/** * Java class 未在此程序中使用,因此未由 JVM 加载 */

class NotUsed {
 static { System.out.println("NotUsed Class is initialized "); }

}

myClass a = new myClass();

我被教导,第一部分是初始化,第二部分在“=”之后是加载。

你可以初始化一个class:

myClass a;

然后稍后在代码中加载它:

a = new myClass();

与变量初始化相同

您对 javaworld 文章感到困惑。虽然有点苛刻,但为了这个答案的目的,我们只说它是错误的并忽略它。

来自jvm specification

The Java Virtual Machine dynamically loads, links and initializes classes and interfaces. Loading is the process of finding the binary representation of a class or interface type with a particular name and creating a class or interface from that binary representation. Linking is the process of taking a class or interface and combining it into the run-time state of the Java Virtual Machine so that it can be executed. Initialization of a class or interface consists of executing the class or interface initialization method

从上面突出显示的文本中,您可以准确地看到加载和初始化的含义以及 javaworld 使用 loading (不正确) 作为他们的总称。

来自jls

12.4.1. When Initialization Occurs

A class or interface type T will be initialized immediately before the first occurrence of any one of the following:

  • T is a class and an instance of T is created.
  • A static method declared by T is invoked.
  • A static field declared by T is assigned.
  • A static field declared by T is used and the field is not a constant variable (§4.12.4).
  • T is a top level class (§7.6) and an assert statement (§14.10) lexically nested within T (§8.1.3) is executed.

来自java重新访问的文章:

NotUsed o = null;
..
class NotUsed {
    static { System.out.println("NotUsed Class is initialized"); }
}

声明一个变量没有被列为导致初始化的事情之一,所以它没有被初始化并且 "NotUsed Class is initialized" 不会被打印出来。规范没有定义是否加载NotUsed,在sun的java上使用默认的ClassLoader 8不会加载。