1. 流程图
2. 详细分析
2.1 加载
找到字节码二进制流并加载到方法区中,在堆中创建对应的 Class 对象。
2.2 链接
分为三步:验证、准备、解析。
2.3 初始化
执行类的类构造方法 <clinit>
。类的初始化往往是延迟执行的,并不是加载后就会执行。 那什么时候执行呢?先来看看 Java 虚拟机规范(Java Virtual Machine Specification)是怎么描述的。
A class or interface C may be initialized only as a result of:
The execution of any one of the Java Virtual Machine instructions new, getstatic, putstatic, or invokestatic that references C (§new, §getstatic, §putstatic, §invokestatic).
Upon execution of a new instruction, the class to be initialized is the class referenced by the instruction.
Upon execution of a getstatic, putstatic, or invokestatic instruction, the class or interface to be initialized is the class or interface that declares the resolved field or method.
The first invocation of a java.lang.invoke.MethodHandle instance which was the result of method handle resolution (§5.4.3.5) for a method handle of kind 2 (REF_getStatic), 4 (REF_putStatic), 6 (REF_invokeStatic), or 8 (REF_newInvokeSpecial).
This implies that the class of a bootstrap method is initialized when the bootstrap method is invoked for an invokedynamic instruction (§invokedynamic), as part of the continuing resolution of the call site specifier.
Invocation of certain reflective methods in the class library (§2.12), for example, in class Class or in package java.lang.reflect.
If C is a class, the initialization of one of its subclasses.
If C is an interface that declares a non-abstract, non-static method, the initialization of a class that implements C directly or indirectly.
Its designation as the initial class or interface at Java Virtual Machine startup (§5.2).
我翻译了上面的一部分语句。这个知道个大概就行,没必要背下来。
一个类或接口 C 可能仅在以下条件时会初始化:
- 执行任意一条引用了 C 的 JVM 字节码指令时,比如:new, getstatic, putstatic, or invokestatic。
- 在执行 new 字节码指令时,要初始化的类是该字节码指令引用的类
- 在执行 getstatic, putstatic, or invokestatic 字节码指令时,要初始化的类或接口是声明了要解析的字段或方法的类或接口
- C 是一个类,它的子类初始化时
- C 作为 JVM 启动类时
那类的初始化可以先于链接(linked)执行吗?
Java 虚拟机规范中这句话一语道破。
Prior to initialization, a class or interface must be linked, that is, verified, prepared, and optionally resolved.
大体意思就是:在类或接口初始化之前,必须被链接,链接过程中执行验证、准备、解析(部分符号引用的解析,在类执行某些字节码指令时也会动态解析符号引用)阶段。