什么是类加载的委派模型?

简介

Java语言采用的是基于类的面向对象编程思想,当Java程序需要使用一个类时,它会根据类的名称来寻找对应的字节码文件,并将字节码文件加载到JVM中。类加载的委派模型是指,当Java程序需要加载一个类时,先委派父类加载器去加载该类,如果父类加载器无法加载该类,则交给当前类加载器自行加载。

工作原理

类加载的委派模型是Java虚拟机(JVM)用来保证Java核心api不被篡改的重要机制之一。在JVM创建时,会设置一个系统类加载器,所有其他的类加载器都是由系统类加载器创建的。类加载器按照父子关系形成了一个树形结构,每个类加载器实例都有一个指向其父类加载器实例的引用。

在实际加载一个类时,JVM会依次将该任务委派给当前线程的父类加载器实例去完成。如果父类加载器可以成功加载该类,加载过程结束。如果父类加载器无法完成加载任务,则将任务转交给他的父类加载器,直到顶层的启动类加载器为止。如果启动类加载器依然找不到要加载的类,则会抛出ClassNotFoundException异常。

这个过程中,一个类被加载时,本质上只是其对应的.class文件被读取到了JVM中,并在JVM的内存区域中生成一个代表该类的Class对象,这个Class对象对于JVM来说是唯一的,即同一个类被加载多次,JVM都只会为其生成一个Class对象。

示例

示例1:

示例代码:

public class MyClassLoader {
    public static void main(String[] args) {
        //获取系统类加载器
        ClassLoader appClassLoader = ClassLoader.getSystemClassLoader();
        System.out.println("系统类加载器:" + appClassLoader);

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

        //获取扩展类加载器的父类加载器——启动类加载器
        ClassLoader bootstrapClassLoader = extensionClassLoader.getParent();
        System.out.println("启动类加载器:" + bootstrapClassLoader);
    }
}

该示例代码输出:

系统类加载器:jdk.internal.loader.ClassLoaders$AppClassLoader@2b193f2d
扩展类加载器:jdk.internal.loader.ClassLoaders$PlatformClassLoader@1f96302d
启动类加载器:null

示例2:

示例代码:

public class ClassLoaderDemo {
    public static void main(String[] args) throws Exception {
        // 获取一个系统类加载器
        ClassLoader systemClassLoader = ClassLoader.getSystemClassLoader();
        // 通过系统类加载器加载一个类
        Class<?> clazz = systemClassLoader.loadClass("java.lang.String");
        // 打印该类的类加载器——因为是由系统类加载器加载的,所以输出是AppClassLoader
        System.out.println("类加载器:" + clazz.getClassLoader());
    }
}

该示例代码输出:

类加载器:jdk.internal.loader.ClassLoaders$AppClassLoader@2b193f2d

总结

类加载器的委派模型是Java虚拟机保证api被加载时不被篡改的重要机制之一。在使用ClassLoader类加载器加载类时,其实是按照委派模型去执行,在每次委派给父ClassLoader加载类时,都会先到其父ClassLoader中查找是否已经加载。这种机制避免了类名相同但来源不同的类出现混乱,从而保证了Java程序的安全性。

本站文章如无特殊说明,均为本站原创,如若转载,请注明出处:什么是类加载的委派模型? - Python技术站

(0)
上一篇 2023年5月10日
下一篇 2023年5月10日

相关文章

  • java实现停车场管理系统

    Java实现停车场管理系统攻略 1.需求分析 停车场管理系统需要实现以下功能: 停车:可以记录车辆的停放时间和位置(车位号) 取车:可以计算车辆停放的费用并将车位号记录,同时从停车记录中删除该车辆 车位管理:对车位进行增删改查,可以查询所有车位和空闲车位 停车记录查询:可以查询所有停车记录以及某个时间段的停车记录 2.数据库设计 使用MySQL数据库存储停车…

    Java 2023年5月24日
    00
  • Java面向对象之继承的概念详解

    Java面向对象之继承的概念详解 继承是面向对象编程的三大特性之一,也是Java程序设计中重要的概念之一。继承允许我们在已有类的基础上定义新的类,新的类可以继承父类的属性和方法,同时可以添加自己的属性和方法。 继承的定义和基本语法 继承(inheritance)是OO(面向对象)技术的一个基本概念,它是从已有类中派生出新的类,新的类可以拥有父类的属性和方法,…

    Java 2023年5月26日
    00
  • Java的Struts框架报错“NullActionForwardException”的原因与解决办法

    当使用Java的Struts框架时,可能会遇到“NullActionForwardException”错误。这个错误通常由以下原因之一起: 配置错误:如果配置文件中没有正确配置,则可能会出现此。在这种情况下,需要检查文件以解决此问题。 转发名称:如果转发名称不正确,则可能出现此。在这种情况下,需要检查转发名称以解决此问题。 以下是两个实例: 例 1 如果配置…

    Java 2023年5月5日
    00
  • JAVA WEB中Servlet和Servlet容器的区别

    下面是关于“JAVA WEB中Servlet和Servlet容器的区别”的完整攻略。 Servlet的定义 Servlet是Java语言编写的服务器端程序,它可以接受客户端(Web浏览器)的请求并生成响应。Servlet通常被用来扩展Web服务器的功能。简单来说,Servlet是一个服务器端的组件,它能够接受来自客户端的请求,并根据该请求执行相应的任务。 S…

    Java 2023年5月19日
    00
  • SpringBoot项目运行jar包启动的步骤流程解析

    下面是关于SpringBoot项目运行jar包启动的步骤流程解析的完整攻略。 1. 编写SpringBoot应用程序 首先,我们需要编写一个SpringBoot应用程序。这里以一个简单的Hello World程序为例: @RestController public class HelloController { @GetMapping("/hell…

    Java 2023年5月19日
    00
  • 一篇文章带你入门Java UML的类图

    下面我将为您详细讲解“一篇文章带你入门Java UML的类图”的完整攻略。 简介 Java UML是Java开发中必不可少的一部分,它可以帮助开发者对Java程序进行设计、开发和维护。其中类图是Java UML的重要组成部分。类图是一种描述类、接口、实现和它们之间关系的图形化方式。 步骤 下面我将向您介绍如何使用Java UML的类图进行Java编程: 1.…

    Java 2023年5月24日
    00
  • spring mvc4的日期/数字格式化、枚举转换示例

    下面是关于“Spring MVC4的日期/数字格式化、枚举转换示例”的完整攻略,包含两个示例说明。 Spring MVC4的日期/数字格式化、枚举转换示例 Spring MVC4提供了强大的数据绑定和类型转换功能,可以自动将HTTP请求参数转换为Java对象,并将Java对象转换为HTTP响应。下面我们将详细介绍Spring MVC4的日期/数字格式化和枚举…

    Java 2023年5月17日
    00
  • JavaScript面向对象三个基本特征实例详解【封装、继承与多态】

    JavaScript面向对象三个基本特征实例详解 在JavaScript中,面向对象编程是一种常用的编程方式,它主要依靠三个基本特征:封装、继承和多态。下面将分别对它们进行详细的说明。 封装 封装是指将数据和行为封装在一个对象中,并对外部提供公共方法进行访问。 下面是一个使用封装的示例: class Person { constructor(name, ag…

    Java 2023年5月23日
    00
合作推广
合作推广
分享本页
返回顶部