Java 中类什么时候加载
在 Java 中,类的加载是指将类的字节码文件加载到内存,并在内存中创建对应的 Class 对象的过程。类的加载是 Java 程序运行的必要环节,只有在类加载完成后,程序才能正常执行和访问类的成员。
类加载的时机
Java 中类的加载时机可以分为以下几种情况:
-
当创建类的实例时:当我们使用
new
关键字创建一个类的实例时,JVM 会首先检查该类是否已经加载,如果没有加载,则会触发类的加载过程。示例代码如下所示:
public class MyClass { // 类的成员和方法 } public class Main { public static void main(String[] args) { MyClass obj = new MyClass(); // 创建 MyClass 的实例 } }
-
当访问类的静态成员时:当我们访问一个类的静态成员(包括静态变量和静态方法)时,JVM 会首先检查该类是否已经加载,如果没有加载,则会触发类的加载过程。
示例代码如下所示:
public class MyClass { public static int myStaticField = 10; // 静态变量 public static void myStaticMethod() { // 静态方法 System.out.println("Hello, World!"); } } public class Main { public static void main(String[] args) { System.out.println(MyClass.myStaticField); // 访问静态变量 MyClass.myStaticMethod(); // 调用静态方法 } }
-
当使用反射访问类时:当我们使用 Java 的反射机制来访问一个类时,JVM 会首先检查该类是否已经加载,如果没有加载,则会触发类的加载过程。
示例代码如下所示:
public class MyClass { // 类的成员和方法 } public class Main { public static void main(String[] args) throws Exception { Class<?> clazz = Class.forName("MyClass"); // 通过类名获取 Class 对象 System.out.println(clazz); } }
-
当执行类的主方法时:当我们执行一个 Java 程序时,JVM 会首先加载包含
public static void main(String[] args)
方法的类,然后再执行该方法。示例代码如下所示:
public class Main { public static void main(String[] args) { System.out.println("Hello, World!"); } }
类加载的过程
当一个类被加载时,JVM 会按照以下步骤进行类的加载过程:
- 加载(Loading):将类的字节码文件加载到内存中。
- 链接(Linking):将字节码文件中的符号引用转换为直接引用,并进行验证、准备和解析等操作。
- 验证(Verification):确保字节码文件的正确性和安全性。
- 准备(Preparation):为类的静态变量分配内存,并设置默认初始值。
- 解析(Resolution):将符号引用转换为直接引用,如将方法的符号引用转换为内存地址。
- 初始化(Initialization):对类的静态变量进行显式初始化和静态代码块的执行。
类加载器
在 Java 中,类加载器(ClassLoader)负责将类的字节码文件加载到内存中。JVM 内置了三个主要的类加载器,分别是:
- 引导类加载器(Bootstrap ClassLoader):负责加载 Java 的核心类,如
java.lang.Object
等,它是 JVM 内置的,没有对应的 Java 类。 - 扩展类加载器(Extension ClassLoader):负责加载扩展类路径(
ext
目录)下的类。 - 应用程序类加载器(Application ClassLoader):负责加载应用程序类路径(
classpath
)下的类。
我们也可以通过自定义类加载器来实现类的加载,以满足特定的需求,如实现热部署等。