JVM工作原理与实战(十):类加载器-Java类加载器

前言

​JVM作为Java程序的运行环境,其负责解释和执行字节码,管理内存,确保安全,支持多线程和提供性能监控工具,以及确保程序的跨平台运行。本文主要介绍了扩展类加载器、通过扩展类加载器去加载用户jar包、应用程序类加载器等内容。


在Java虚拟机(JVM)中,类加载器负责将类的字节码文件加载到内存中,并生成对应的Class对象。类加载器是Java虚拟机中的重要组成部分,其中Java代码实现的类加载器包括扩展类加载器和应用程序类加载器(JDK8及之前的版本)。

一、介绍

扩展类加载器和应用程序类加载器是JDK中提供的、使用Java编写的类加载器。它们是sun.misc.Launcher的静态内部类,并继承自URLClassLoader。这两个类加载器具备通过目录或指定jar包将字节码文件加载到内存中的能力。此外,它们还提供了更多的功能和灵活性,以支持Java应用程序的动态类加载需求。

ClassLoader 抽象类,定义了类加载器的具体行为模式,通过JNI调用底层的Java虚拟机方 法。
SecureClassLoader 使用证书机制提升类加载的安全性。
URLClassLoader 利用URL获取目录下或者指定的jar包进行加载,获取其字节码数据。
扩展类加载器****Extension 加载Java安装目录/jre/lib/ext下的类文件。
应用程序类加载器****Application 加载classpath下的类文件。

二、扩展类加载器

扩展类加载器(Extension Class Loader)是JDK中提供的一个功能强大的类加载器,它使用Java语言编写,用于加载Java安装目录/jre/lib/ext下的类文件。该加载器继承自Java的URLClassLoader类,具有高度的灵活性和可扩展性,能够根据需要动态地加载和卸载类文件,从而满足Java应用程序的多样化需求。

ClassLoader提供了许多方法来动态加载类,如loadClass()、defineClass()等。这些方法允许程序员在运行时动态地加载类的字节码文件,并生成对应的Class对象。

案例:

获取扩展类加载器:

arduino 复制代码
public class ExtClassLoaderDemo {
    public static void main(String[] args){
        ClassLoader classLoader = ScriptEnvironment.class.getClassLoader();
        System.out.println(classLoader);
    }
}

运行结果:

三、通过扩展类加载器去加载用户jar包

通过将所需的jar包放入/jre/lib/ext目录下和使用参数进行扩展两种方法,开发者可以利用扩展类加载器来加载用户提供的JAR包。在使用时,请根据具体情况选择最适合的方式,并注意避免可能出现的冲突和问题。

1.放入/jre/lib/ext下进行扩展

一种直接的方法是将所需的jar包放入/jre/lib/ext目录下,让扩展类加载器能够加载到这个jar包中的类。尽管这种方法能够使 JAR 包被类加载器加载,但并不推荐。主要原因是这涉及到更改 JDK 安装目录中的内容,可能会引发不可预测的问题,也可能影响到 JDK 的升级。

2.使用参数进行扩展

推荐,使用-Djava.ext.dirs=jar包目录进行扩展。这种方式可以加载用户提供的 JAR 包,但是会覆盖原始目录。所以在Windows上,可以使用分号(;)来分隔多个目录,在MacOS和Linux上,可以使用冒号(:)来分隔多个目录。

案例:

加载jar包(省略用户JAR包打包步骤):

ini 复制代码
public class Demo2 {
    public static void main(String[] args) throws ClassNotFoundException {
        Class<?> aClass = Class.forName("com.rye.test.Test");
        System.out.println(aClass);
        ClassLoader classLoader = aClass.getClassLoader();
        System.out.println(classLoader);
//        验证没有覆盖原始目录
        ClassLoader loader = ScriptEnvironment.class.getClassLoader();
        System.out.println(loader);
    }
}

使用-Djava.ext.dirs=jar包目录进行扩展:

ini 复制代码
-Djava.ext.dirs=jar包目录
ini 复制代码
-Djava.ext.dirs="D:\Java\jdk1.8.0_201\jre\lib\ext;D:\Test"

运行结果:

四、应用程序类加载器

应用程序类加载器(Application Class Loader)也是JDK中提供的、使用Java编写的类加载器。它的主要任务是加载应用程序的classpath下的类文件。

案例:

获取应用程序类加载器:

csharp 复制代码
public class AppClassLoader {
    public static void main(String[] args) {
        // 该项目创建的Student类
        Student student = new Student();
        ClassLoader classLoader = Student.class.getClassLoader();
        System.out.println(classLoader);

        // maven依赖中的类
        ClassLoader classLoader1 = FileUtils.class.getClassLoader();
        System.out.println(classLoader1);
    }
}

运行结果:


总结

JVM是Java程序的运行环境,负责字节码解释、内存管理、安全保障、多线程支持、性能监控和跨平台运行。本文主要介绍了扩展类加载器、通过扩展类加载器去加载用户jar包、应用程序类加载器等内容,希望对大家有所帮助。

相关推荐
橙序员小站3 分钟前
当所有人都在做 Agent,我想聊聊被遗忘的基础设施
后端·开源·aigc
小蚂蚁i3 分钟前
LangChain 完全学习手册:看完就能上手
后端·python·ai编程
Memory_荒年4 分钟前
TiDB:当 MySQL 遇上分布式,生了个“超级混血儿”
java·数据库·后端
asom227 分钟前
DDD(领域驱动设计) 核心概念详解
java·开发语言·数据库·spring boot
一步一个脚印一个坑16 分钟前
用 APM 全链路追踪,29ms 内定位到 Docker 部署的 SSL 配置错误
javascript·后端·监控
aircrushin33 分钟前
端到端AI决策架构如何重塑实时协作体验?
前端·javascript·后端
苦瓜小生40 分钟前
【黑马点评学习笔记 | 实战篇 】| 6-Redis消息队列
redis·笔记·后端
Aawy12041 分钟前
Python生成器(Generator)与Yield关键字:惰性求值之美
jvm·数据库·python
大傻^1 小时前
LangChain4j Spring Boot Starter:自动配置与声明式 Bean 管理
java·人工智能·spring boot·spring·langchain4j
沐硕1 小时前
《基于改进协同过滤与多目标优化的健康饮食推荐系统设计与实现》
java·python·算法·fastapi·多目标优化·饮食推荐·改进协同过滤