首页 > 编程语言 >Java 类加载、类加载器及双亲委派机制详解

Java 类加载、类加载器及双亲委派机制详解

时间:2024-12-03 14:47:05浏览次数:4  
标签:Java JDK System 器及 println out 加载

Java 类加载、类加载器及双亲委派机制详解

在Java中,类加载是JVM运行的重要环节,而类加载器则是负责将.class文件加载到内存中的核心组件。本文详细介绍类加载的过程、类加载器的工作机制及双亲委派机制,同时比较Oracle JDK 8与JDK 9及之后版本在类加载器上的变化。


1. 类的加载

类的加载是什么?

类的加载是指将一个Java类的.class文件读入内存,并转化为一个Class对象。类的加载只会在类第一次被使用时触发,例如:

  1. 创建类的实例(new关键字)。
  2. 调用类的静态方法或访问静态字段。
  3. 使用类的子类(会触发父类加载)。
  4. 通过反射加载类。
  5. 使用java命令运行类。

类加载过程

类加载主要分为以下三个阶段:

  1. 加载:将.class文件的字节码读入内存,生成Class对象。
  2. 链接
    • 验证:确保字节码文件格式合法。
    • 准备:为类的静态变量分配内存并初始化为默认值。
    • 解析:将符号引用解析为直接引用。
  3. 初始化:执行静态代码块和静态字段赋值。

代码示例:类加载过程

public class Demo {
    static {
        System.out.println("Class Demo is being initialized");
    }

    public static void main(String[] args) {
        System.out.println("Main method executed");
    }
}

运行时,类加载顺序如下:

  1. 加载Demo类的.class文件。
  2. 链接:验证、准备静态变量。
  3. 初始化:执行静态代码块。

输出:

Class Demo is being initialized
Main method executed

2. 类加载器

类加载器是什么?

类加载器是JVM中负责加载字节码文件并生成Class对象的组件。每个类加载器负责加载特定范围的类。

类加载器的分类

Java中的类加载器主要分为三种:

  1. 启动类加载器(Bootstrap ClassLoader)
    • 负责加载JVM的核心类库,如rt.jar
    • 由本地代码实现,不是Java类对象。
  2. 扩展类加载器(Extension ClassLoader)
    • 加载<JAVA_HOME>/lib/ext目录下的扩展类库。
  3. 应用程序类加载器(Application ClassLoader)
    • 加载CLASSPATH中指定的类,是程序的默认类加载器。

获取类加载器

代码示例:

public class ClassLoaderDemo {
    public static void main(String[] args) {
        // 获取当前类的类加载器
        ClassLoader appClassLoader = ClassLoaderDemo.class.getClassLoader();
        System.out.println("应用程序类加载器: " + appClassLoader);

        // 获取父加载器(扩展类加载器)
        ClassLoader extClassLoader = appClassLoader.getParent();
        System.out.println("扩展类加载器: " + extClassLoader);

        // 获取父加载器的父加载器(启动类加载器,返回 null)
        ClassLoader bootstrapClassLoader = extClassLoader.getParent();
        System.out.println("启动类加载器: " + bootstrapClassLoader);
    }
}

运行结果(JDK 8):

应用程序类加载器: sun.misc.Launcher$AppClassLoader@2a139a55
扩展类加载器: sun.misc.Launcher$ExtClassLoader@7e774085
启动类加载器: null

3. 双亲委派机制

双亲委派机制是什么?

双亲委派机制是类加载器的一种设计模式,其核心思想是:

  1. 类加载器在加载类时,首先将加载请求委托给父加载器。
  2. 父加载器尝试加载,如果无法加载,则由当前加载器加载。

工作流程

假设需要加载类Demo

  1. 应用程序类加载器收到加载请求,先委托给扩展类加载器。
  2. 扩展类加载器再委托给启动类加载器。
  3. 启动类加载器尝试加载类。
  4. 如果启动类加载器无法加载,返回给扩展类加载器,最终由应用程序类加载器加载。

优点

  1. 安全性:避免核心类(如java.lang.String)被用户自定义类加载器篡改。
  2. 避免重复加载:同一个类只会被加载一次。

4. JDK 8 与 JDK 9 类加载器的变化

代码对比

JDK 8:

@Test
public void testClassLoader() {
    ClassLoader classLoader = Demo.class.getClassLoader();

    System.out.println(classLoader); // sun.misc.Launcher$AppClassLoader@22d8cfe0
    System.out.println(classLoader.getParent()); // sun.misc.Launcher$ExtClassLoader@65e579dc
    System.out.println(classLoader.getParent().getParent()); // null
}

JDK 9:

@Test
public void testClassLoader() {
    ClassLoader classLoader = Demo.class.getClassLoader();

    System.out.println(classLoader); // jdk.internal.loader.ClassLoaders$AppClassLoader@726f3b58
    System.out.println(classLoader.getParent()); // jdk.internal.loader.ClassLoaders$PlatformClassLoader@e73f9ac
    System.out.println(classLoader.getParent().getParent()); // null
}

主要区别

  1. 扩展类加载器改为平台类加载器
    • JDK 8:扩展类加载器(sun.misc.Launcher$ExtClassLoader)。
    • JDK 9:平台类加载器(jdk.internal.loader.ClassLoaders$PlatformClassLoader)。
  2. 模块化系统引入
    • JDK 9拆分了rt.jar,通过模块系统加载核心类。
    • 平台类加载器专门用于加载模块化系统中的类。

原因

  • 模块化需求:JDK 9采用Java模块系统(JPMS),优化了类加载器设计。
  • 安全性增强:移除了sun.misc包中的非标准实现。

总结

  1. 类的加载分为加载、链接、初始化三个阶段,类加载的触发条件包括首次使用类、反射等。
  2. 类加载器分为启动类加载器、扩展类加载器和应用程序类加载器,工作机制采用双亲委派模型。
  3. 双亲委派机制保证了类加载的安全性和高效性。
  4. JDK 9通过模块化改进了类加载器的设计,使用平台类加载器取代扩展类加载器,取消了双亲委派机制,提高了加载效率

通过理解类加载和类加载器的工作原理,可以更好地掌握Java应用程序的运行机制,确保开发的应用安全稳定。

标签:Java,JDK,System,器及,println,out,加载
From: https://www.cnblogs.com/itcq1024/p/18584040

相关文章