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

简介

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基础的详细了解第七天攻略 在第七天的学习中,我们将了解Java的异常处理机制。异常是指程序运行期间发生的不正常情况,如除数为0,数组越界等等。在Java中,异常处理机制提供了异常的捕获、处理和抛出的操作,可以帮助我们提高程序的健壮性。 异常类的层次结构 在Java中,异常类是按照树形结构进行组织的,最顶层是Throwable类,下面分为两个子类,分别…

    Java 2023年5月23日
    00
  • editplus配置java编程环境详细介绍

    EditPlus配置Java编程环境详细介绍 EditPlus是一款文本编辑器,它可以为Java编程者提供良好的编程环境。以下是EditPlus的Java编程环境配置攻略,包括Java 开发工具包(JDK)和编译器环境的配置。 JDK安装 首先,我们需要下载最新的JDK。当前最新版本是JDK 16。通过Oracle官网下载JDK 安装程序并开始安装过程。 安…

    Java 2023年5月23日
    00
  • Spring系列中的beanFactory与ApplicationContext

    当提到Spring框架的IoC容器时,很容易想到beanFactory和ApplicationContext,这两者都属于Spring框架中IoC容器的范畴。本篇文章将详细讲解beanFactory和ApplicationContext的特点,优缺点以及使用场景。 BeanFactory BeanFactory是Spring框架最基本的IoC容器,提供了一种…

    Java 2023年5月19日
    00
  • Spring Boot接口幂等插件用法示例解析

    Spring Boot接口幂等插件用法示例解析攻略 本文将详细介绍Spring Boot接口幂等插件的用法,并给出两个实例说明。 1. 简介 在分布式的应用中,为了保障数据的一致性,常常需要保证接口的幂等性。Spring Boot提供一个开源插件spring-boot-starter-idempotency来保证这一点。 该插件使用Redis来实现幂等性的检…

    Java 2023年5月26日
    00
  • Java面试问题知识点总结

    Java面试问题知识点总结 Java开发人员在准备面试时需要了解重要的Java面试问题知识点。这是一个综合性的总结,包括Java基础知识,Java程序设计、Java集合、Java并发和多线程、Java面向对象特性和JVM等主题。 Java基础知识 Java基础知识包括Java程序的基础、Java的数据类型、Java的运算符、流程控制语句和异常处理等。 在基础…

    Java 2023年5月20日
    00
  • SpringBoot 整合mybatis+mybatis-plus的详细步骤

    下面是 “SpringBoot整合MyBatis和MyBatis-Plus的详细步骤”。 1. 添加依赖 首先,在 pom.xml 中添加以下依赖: <!– SpringBoot 整合 MyBatis 依赖 –> <dependency> <groupId>org.mybatis.spring.boot</gro…

    Java 2023年5月20日
    00
  • SpringMVC访问静态资源的方法

    以下是关于“SpringMVC访问静态资源的方法”的完整攻略,其中包含两个示例。 SpringMVC访问静态资源的方法 SpringMVC是一种基于Java的Web框架,它可以帮助我们快速开发Web应用程序。在本文中,我们将讲解如何在SpringMVC中访问静态资源。 方法一:使用标签 在src/main/webapp目录下创建一个名为static的文件夹。…

    Java 2023年5月17日
    00
  • Log4j 配置日志打印时区的实现方法

    下面是具体的攻略: 1. 前言 Log4j 是一个非常优秀的 Java 日志组件,其可以方便的对 Java 应用的运行时状态进行记录和追踪。在对日志进行格式化输出时,Log4j 默认使用的是本地的时间,而不是 UTC 时间。这就导致在跨时区的场景下,输出的时间可能会出现时间误差的问题。因此,在 Log4j 中配置时区信息是非常必要的。 2. 实现方法 2.1…

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