【小家Java】从原理层面理解Java中的类加载器:ClassLoader、双亲委派模型、线程上下文类加载器(下)

本文涉及的产品
RDS MySQL DuckDB 分析主实例,集群系列 4核8GB
RDS MySQL DuckDB 分析主实例,基础系列 4核8GB
RDS AI 助手,专业版
简介: 【小家Java】从原理层面理解Java中的类加载器:ClassLoader、双亲委派模型、线程上下文类加载器(下)

线程上下文类加载器


该加载器十分的重要,也十分的优雅。在Tomcat和Spring中有大量的应用。作为补充,它可以补充JDK提供的三种加载器不能实现的功能,使之更为灵活。


双亲委派模型痛点场景:


Java 提供了很多服务提供者接口(Service Provider Interface,SPI),允许第三方为这些接口提供实现。常见的 SPI 有 JDBC(Java官方并不提供具体实现,而是由各自的数据库厂商去实现)、JCE、JNDI、JAXP 和 JBI 等。


SPI接口均由Java核心库来提供,而实现代码都为其余厂商提供(一般都在我们引入的第三方jar包里面)。所以问题就来了:SPI接口中的代码经常需要加载具体的实现类,也就是说我再加载JDBC的时候就需要有实现类。 但是SPI接口是Bootstrap Classloader来加载的,而实现类在类路径由AppClassLoader来加载,所以SPI加载的时候铁定就加载不到实现类了。(因为违反了层级委托关系嘛)


解决方案:JDK1.2提供了上下文类加载器来解决此问题。它破坏了“双亲委派模型”,可以在执行线程中抛弃双亲委派加载链模式,使程序可以逆向使用类加载器。看了很多博文,我一直都不理解它具体是如何打破“双亲委派模型”呢?知道我看到了JDBC驱动的加载过程,才彻底的了解了里面的原因~


写个案例:


    public static void main(String[] args) throws SQLException {
        //Class.forName("com.mysql.jdbc.Driver");
        Connection conn = java.sql.DriverManager.getConnection("jdbc:mysql://localhost:3306/jedi", "name", "password");
        System.out.println(conn); //com.mysql.jdbc.JDBC4Connection@15d0c81b
    }


细心的朋友会发现,我把平时我们认为必须要写的Class.forName("com.mysql.jdbc.Driver");这句代码去掉了,但程序还是能正常运行获取到链接。

这是为什么呢?这是因为从Java1.6开始自带的jdbc4.0版本已支持SPI服务加载机制,只要mysql的jar包在类路径中,就可以注册mysql驱动。


那到底是在哪一步自动注册了mysql driver的呢?重点就在DriverManager.getConnection()中。我们都是知道调用类的静态方法会初始化该类静态代码块,so玄机就在这个DriverManager的静态代码块里。


当然里面玄机还有很多,但核心原理就是利用到了上下文加载器来实现加载,具体各位可以下面博文,它比我说得好~

Java上线文加载器加载JDBC驱动

image.png


URLClassLoader


位于java.net包。从JDK源码上来看其实是URLClassLoader继承了ClassLoader,也就是说URLClassLoader把ClassLoader扩展了一下,所以可以理解成URLClassLoader功能要多点。


ClassLoader只能加载classpath下面的类,而URLClassLoader可以加载**任意路径**下的类。他

们的继承关系如下:

public class URLClassLoader extends SecureClassLoader {}
public class SecureClassLoader extends ClassLoader {}


URLClassLoader提供了这个功能,它让我们可以通过以下几种方式进行加载:

* 文件: (从文件系统目录加载)

* jar包: (从Jar包进行加载)

* Http: (从远程的Http服务进行加载)


在Java7的Build 48版中,URLClassLoader提供了close()这个方法,可以将打开的资源全部释放掉,这个给开发者节省了大量的时间来精力来处理这方面的问题。

image.png


URLClassLoader 是AppClassLoader和ExtClassLoader的父类,它既可以从本地 文件系统获取二进制加载类,也可以从远程主机获取文件来加载类。


URLClassLoader 动态加载远程jar的代码实现:

借助URLClassLoader 来读取外部的jar包内的class文件,参考下面这个链接:

java中使用URLClassLoader访问外部jar包的java类


总结


以上是关于类加载器的一些介绍和工作原理。知道委托、可见性以及单一性原理,这些对于调试类加载器相关问题时至关重要。这些对于Java高级程序员和架构师来说都是必不可少的知识。

相关实践学习
如何快速连接云数据库RDS MySQL
本场景介绍如何通过阿里云数据管理服务DMS快速连接云数据库RDS MySQL,然后进行数据表的CRUD操作。
MySQL数据库入门学习
本课程通过最流行的开源数据库MySQL带你了解数据库的世界。   相关的阿里云产品:云数据库RDS MySQL 版 阿里云关系型数据库RDS(Relational Database Service)是一种稳定可靠、可弹性伸缩的在线数据库服务,提供容灾、备份、恢复、迁移等方面的全套解决方案,彻底解决数据库运维的烦恼。 了解产品详情: https://www.aliyun.com/product/rds/mysql 
相关文章
|
9月前
|
存储 缓存 Java
我们来详细讲一讲 Java NIO 底层原理
我是小假 期待与你的下一次相遇 ~
293 2
|
8月前
|
监控 Java API
现代 Java IO 高性能实践从原理到落地的高效实现路径与实战指南
本文深入解析现代Java高性能IO实践,涵盖异步非阻塞IO、操作系统优化、大文件处理、响应式网络编程与数据库访问,结合Netty、Reactor等技术落地高并发应用,助力构建高效可扩展的IO系统。
236 0
|
10月前
|
存储 缓存 Java
【高薪程序员必看】万字长文拆解Java并发编程!(5):深入理解JMM:Java内存模型的三大特性与volatile底层原理
JMM,Java Memory Model,Java内存模型,定义了主内存,工作内存,确保Java在不同平台上的正确运行主内存Main Memory:所有线程共享的内存区域,所有的变量都存储在主存中工作内存Working Memory:每个线程拥有自己的工作内存,用于保存变量的副本.线程执行过程中先将主内存中的变量读到工作内存中,对变量进行操作之后再将变量写入主内存,jvm概念说明主内存所有线程共享的内存区域,存储原始变量(堆内存中的对象实例和静态变量)工作内存。
304 0
|
9月前
|
存储 算法 安全
Java中的对称加密算法的原理与实现
本文详细解析了Java中三种常用对称加密算法(AES、DES、3DES)的实现原理及应用。对称加密使用相同密钥进行加解密,适合数据安全传输与存储。AES作为现代标准,支持128/192/256位密钥,安全性高;DES采用56位密钥,现已不够安全;3DES通过三重加密增强安全性,但性能较低。文章提供了各算法的具体Java代码示例,便于快速上手实现加密解密操作,帮助用户根据需求选择合适的加密方案保护数据安全。
572 58
|
8月前
|
人工智能 安全 Java
Go与Java泛型原理简介
本文介绍了Go与Java泛型的实现原理。Go通过单态化为不同类型生成函数副本,提升运行效率;而Java则采用类型擦除,将泛型转为Object类型处理,保持兼容性但牺牲部分类型安全。两种机制各有优劣,适用于不同场景。
343 24
|
8月前
|
人工智能 前端开发 安全
Java开发不可不知的秘密:类加载器实现机制
类加载器是Java中负责动态加载类到JVM的组件,理解其工作原理对开发复杂应用至关重要。本文详解类加载过程、双亲委派模型及常见类加载器,并介绍自定义类加载器的实现与应用场景。
330 4
|
9月前
|
XML JSON Java
Java 反射:从原理到实战的全面解析与应用指南
本文深度解析Java反射机制,从原理到实战应用全覆盖。首先讲解反射的概念与核心原理,包括类加载过程和`Class`对象的作用;接着详细分析反射的核心API用法,如`Class`、`Constructor`、`Method`和`Field`的操作方法;最后通过动态代理和注解驱动配置解析等实战场景,帮助读者掌握反射技术的实际应用。内容翔实,适合希望深入理解Java反射机制的开发者。
751 13
|
8月前
|
存储 缓存 安全
深入讲解 Java 并发编程核心原理与应用案例
本教程全面讲解Java并发编程,涵盖并发基础、线程安全、同步机制、并发工具类、线程池及实际应用案例,助你掌握多线程开发核心技术,提升程序性能与响应能力。
316 0
|
9月前
|
算法 Java 索引
说一说 Java 并发队列原理剖析
我是小假 期待与你的下一次相遇 ~