Java 类加载器(ClassLoader)

Java 中的类加载器是用于加载 .class 文件到 JVM 中的组件,它的核心作用是将字节码(.class 文件)加载到内存,并且使它能够被 JVM 执行。类加载器决定了类的加载顺序和加载方式,是 Java 应用程序在运行时执行的重要部分。

1. 类加载器的基本概念

  • 类加载器:Java 中的类加载器用于将 .class 文件加载到 JVM 中,并将其转化为一个 Class 对象,之后该 Class 对象可以用于反射等操作。
  • 每个类加载器都具备加载类的能力,但它们的加载范围和加载顺序可能不同。

2. 类加载器的类型

2.1 根类加载器(Bootstrap ClassLoader)

  • 作用:是最顶层的类加载器,负责加载 Java 核心库中的类,如 java.lang.*java.util.*
  • 实现:Bootstrap ClassLoader 是由 C++ 实现的,通常由操作系统提供,加载 jre/lib 目录下的类库。
  • 加载路径:由环境变量 sun.boot.class.path 指定。

2.2 扩展类加载器(Extension ClassLoader)

  • 作用:负责加载 JDK 中的扩展类库,主要加载 jre/lib/ext 目录下的类库。
  • 实现:它是由 Java 实现的,继承自 ClassLoader
  • 加载路径:由 java.ext.dirs 指定。

2.3 系统类加载器(System ClassLoader)

  • 作用:也叫应用类加载器,负责加载应用程序的类路径(classpath)下的类。
  • 实现:由 Java 实现,通常是用户应用程序使用的加载器,加载 classpath 中的类。
  • 加载路径:由环境变量 java.class.path 指定。

2.4 自定义类加载器(Custom ClassLoader)

  • 作用:开发人员可以自定义类加载器,继承 ClassLoader 类,重写 findClass() 方法来加载类。
  • 应用场景
    • 加载本地文件、数据库、网络等外部资源中的类。
    • 用于 Web 服务器(如 Tomcat)中动态加载 JSP 文件或动态加载插件等。

3. 类加载的过程

3.1 加载(Load)

  • 类加载器根据类名查找 .class 文件,并读取它的字节流。
  • 这个过程会依赖于类加载器的父子关系,父加载器优先加载。

3.2 链接(Linking)

链接分为三个阶段:

  1. 验证(Verify):检查字节码是否符合 JVM 的要求,防止非法代码进入。
  2. 准备(Prepare):为类的静态变量分配内存并赋默认值。
  3. 解析(Resolve):将常量池中的符号引用替换为直接引用。

3.3 初始化(Initialize)

  • 在类的初始化阶段,JVM 执行类的静态代码块(static 块),初始化静态变量等。

4. 类加载器的双亲委派机制(Parent Delegation Model)

  • 双亲委派模型是 Java 类加载器的一个重要特点,它确保了类加载的安全性和稳定性。
  • 原理
    • 每个类加载器都有一个父类加载器。当一个类加载请求发生时,子加载器会先将请求传递给父加载器,父加载器先尝试加载该类。如果父加载器加载失败,子加载器再尝试加载。
    • 这确保了 Java 核心类库(如 java.lang.*)始终由根类加载器加载,从而避免了重复加载和潜在的冲突。

5. 自定义类加载器的示例

通过继承 ClassLoader 类,我们可以创建自己的类加载器,下面是一个简单的自定义类加载器示例:

public class MyClassLoader extends ClassLoader {
@Override
public Class<?> findClass(String name) throws ClassNotFoundException {
byte[] classData = loadClassData(name); // 从某个源(如文件、数据库)获取字节数据
return defineClass(name, classData, 0, classData.length);
} private byte[] loadClassData(String name) {
// 加载类的字节数据(例如,从文件或网络中读取)
return new byte[0]; // 示例返回空字节数组
}
} public class Test {
public static void main(String[] args) throws Exception {
MyClassLoader loader = new MyClassLoader();
Class<?> clazz = loader.loadClass("com.example.MyClass");
Object obj = clazz.newInstance();
}
}

解释:

  • MyClassLoader 继承自 ClassLoader,重写 findClass 方法来从某个地方加载类的字节数据。
  • loadClassData 方法是我们用来加载类字节数据的地方,可以从文件、数据库等地方加载。
  • defineClass 方法将字节数据转换为一个 Class 对象。

6. 类加载器的应用场景

  • 动态加载插件:在应用程序运行时,动态加载新的功能模块或插件,避免重新启动应用。
  • Web 服务器:如 Tomcat 会使用不同的类加载器来加载 Web 应用中的类,保证每个应用使用独立的类加载器。
  • 类版本控制:在某些情况下,自定义类加载器可以用来控制不同版本的类加载,避免类冲突。

7. 总结

  • 类加载器是 Java 中用于加载 .class 文件的组件,分为根类加载器、扩展类加载器、系统类加载器和自定义类加载器。
  • 双亲委派机制保证了类加载的顺序和安全性。
  • 自定义类加载器为我们提供了灵活性,可以从本地文件、网络等加载类,支持插件化开发。

你了解 Java 的类加载器吗?的更多相关文章

  1. java自定义类加载器

    前言 java反射,最常用的Class.forName()方法.做毕设的时候,接收到代码字符串,通过 JavaCompiler将代码字符串生成A.class文件(存放在classpath下,也就是ec ...

  2. Java虚拟机类加载器及双亲委派机制

    所谓的类加载器(Class Loader)就是加载Java类到Java虚拟机中的,前面<面试官,不要再问我"Java虚拟机类加载机制"了>中已经介绍了具体加载class ...

  3. 深入探讨java的类加载器

    类加载器是 Java 语言的一个创新,也是 Java 语言流行的重要原因之一.它使得 Java 类可以被动态加载到 Java 虚拟机中并执行.类加载器从 JDK 1.0 就出现了,最初是为了满足 Ja ...

  4. java 中类加载器

    jar 运行过程和类加载机制有关,而类加载机制又和我们自定义的类加载器有关,现在我们先来了解一下双亲委派模式. java 中类加载器分为三个: BootstrapClassLoader 负责加载 ${ ...

  5. java高新技术-类加载器

    1.类加载器及委托机制的深入分析 > 类加载器的作用:一个java文件中的出现的类,首先要把这个类的字节码加载到内存中,这个类的信息放在硬盘的classPath下的class文件中,  把cla ...

  6. 深入理解Java虚拟机 - 类加载器

    引子:       类加载器(classloader)是独立于虚拟机之外,可以独立实现的代码模块.     OSGi使用了类加载器的这一特点实现其热插拔的特性       Java同C++等语言不通, ...

  7. 分析Java的类加载器与ClassLoader(二):classpath与查找类字节码的顺序,分析ExtClassLoader与AppClassLoader的源码

    先回顾一下classpath classpath的作用: classpath的作用是指定查找类的路径:当使用java命令执行一个类(类中的main方法)时,会从classpath中进行查找这个类. 指 ...

  8. java面向对象--类加载器及Class对象

    类加载器 jvm 和 类的关系 当调用 java命令运行一个java程序时,会启动一个java虚拟机进程.同一个jvm的所有线程.所有变量都处于同一个进程里,都使用该jvm进程的内存区. jvm进程终 ...

  9. Java的类加载器

    一.类加载器的概念 类加载器(class loader)用来加载 Java 类到 Java 虚拟机中.一般来说,Java 虚拟机使用 Java 类的方式如下:Java 源程序(.java 文件)在经过 ...

  10. Java的类加载器种类(双亲委派)

    Java类加载器采用双亲委派模型: 1.启动类加载器:这个类加载器负责放在<JAVA_HOME>\lib目录中的,或者被-Xbootclasspath参数所指定的路径中的,并且是虚拟机识别 ...

随机推荐

  1. 使用iceberg-flink读取iceberg v2表

    一.背景 mysql数据入湖后,有同事需要实时抽取iceberg v2表,想通过iceberg做分钟级实时数仓.目前flink社区暂不支持读取v2表.腾讯内部支持 目前只能用Oceanus内置conn ...

  2. Codeforces 1536B Prinzessin der Verurteilung 题解 [ 紫 ] [ 后缀自动机 ] [ 动态规划 ] [ 拓扑排序 ]

    Prinzessin der Verurteilung:最短未出现字符串的板子. 思路 考虑在 SAM 上 dp,定义 \(dp_i\) 表示从 \(i\) 节点走到 NULL 节点所花费的最少步数. ...

  3. 库卡KUKA机器人KRC4伺服马达维修指导分析

    通常情况下,库卡机器人伺服电机是实现机器人的关键组件,它提供了动力.位置和速度控制力和扭矩控制以及闭环控制等功能,使得库卡机器人能够在各种应用场景中发挥机器本身的性能. 一. 如果KUKA库卡机器人K ...

  4. autMan奥特曼机器人-跳过注册页面直接进入登陆页面

    1.将下面4行内容存成txt文件[注意将"账号"和"密码"等字眼替换为自己的真正账号和密码],文件名改成sets.conf,放到autman主文件夹,见下图最下 ...

  5. autMan奥特曼机器人--可爱猫对接微信教程

    教程开始 文章底部下载可爱猫框架以及对应的微信版本 1.安装3.4.0.38版本微信,解压可爱猫框架压缩包 如果微信安装了高于3.4.0.38的版本,请先卸载 2.打开可爱猫框架,会弹微信扫码登录,机 ...

  6. JavaUtils - [03] 代码生成器(旧)

    题记部分 001 || 引入依赖 <!-- Code Generator --> <dependency> <groupId>com.baomidou</gr ...

  7. mysql扫描全表更新状态部分失败

    1. mysql排序问题 一直以为mysql是按照主键排序的,实则排序和主键没有关系(不使用 order by 子句). 然后从 stackoverflow 上查了一下,找到了以下的回答: 没有默认的 ...

  8. 【Python-Json】自定义类输入json序列化、json的读取与写入

    AI 问答 Question json支持numpy数组么 Answer 不幸的是,标准的 JSON格式 不直接支持 NumPy 数组.JSON是一种用于存储和交换数据的文本格式,它有限的数据类型只包 ...

  9. ITSM运维管理整理总结

    ITSM 和我们平常所说的软件管理最大的不同? 目标不是管理技术,主要任务是管理用户和客户的IT需求 2.人员.技术.流程[重要] 3.几大模块 模块名称 干什么 备注 服务台 1.对接客户的前方,负 ...

  10. glib-2.60在win64,msys2下编译

    前阵子,工作原因,需要在win7 64下的msys2来编译glib,下面是一些踩过的坑: 事先声明一下,这些个解决方式及纯粹是为了编译通过,可能有些做法不太适合一些需要正常使用的场合,烦请各位注意下. ...