线程上下文类加载器

线程上下文类加载器( Thread Context ClassLoader) 是从JDK1.2 引入的,类Thread 的getContextClassLoader() 与 setContextClassLoader(Classloader var1) 分别用来设置线程的上下文类加载器。如果没有指定线程的上下文的加载器,那么线程将会继承父线程的上下文类加载器。Java 的初始化线程的上下文加载器,可以通过上下文类加载器加载类与资源。

基本的获取和使用方法:

public class ContextClassLoader {

/**

* 每个类都会使用自己的类加载器尝试去加载所依赖的类

*

*

如果ClassX 依赖了 ClassY ,那么在ClassX的加载器将会在主动引用ClassY 并且ClassY尚未被加载的时候加载ClassY 这个类

*/

public static void main(String[] args) {

System.out.println(Thread.currentThread().getContextClassLoader());

System.out.println(Thread.class.getClassLoader());

}

}

从 JDBC 说起

在以前学习JDBC 的时候我们最深刻的印象应该是 Class.forName("xxxxxx"); 简单的伪代码如下图:

import java.sql.Connection;

import java.sql.DriverManager;

import java.sql.ResultSet;

import java.sql.Statement;

public class DbUtil {

public static final String URL = "jdbc:mysql://localhost:3306/db";

public static final String USER = "root";

public static final String PASSWORD = "123456";

public static void main(String[] args) throws Exception {

Class.forName("com.mysql.jdbc.Driver");

Connection conn = DriverManager.getConnection(URL, USER, PASSWORD);

Statement stmt = conn.createStatement();

ResultSet rs = stmt.executeQuery("SELECT user_name, age FROM student");

}

}

}

从上面的代码中,import导入的 jdbc 的相关类可以看到,他们均来自于 java.sql 包下,根据类的双亲委派机制可以非常清晰的知道,这些接口肯定是来自于 系统类加载器加载。那么具体的其实现类使用我们的应用类加载器加载,所以问题出现 其中的JDBC 标准是由启动器类加载器加载,而具体的实现的类是由系统类加载器加载,所以这就会导致启动类加载器加载的JDBC标准类无法找到子加载器加载的JDBC实现

TCC 的作用: 改变双亲委托模型

上面的实现模式,我们称之为SPI (服务提供接口) ,这种服务方式通过类的双亲委派机制就会出现问题。

这是加载器双亲委派模型的一个缺陷,但是JVM设计者做了一个不太优雅的的方式解决,就是线程上下文类的加载器,  父 ClassLoader 可以使用 Thread.currentThread().getContextClassloader() 所制定的Classloader 加载的类,这就改变了父ClassLoader不能使用子ClassLoader加载的类以及其他没有父子关系的加载器加载类的访问情况,即改变了双亲委托模型。

Java中所有涉及SPI的加载动作都采用这种方式, 实现方案包括:  JDBC、JNDI、JCE以及JBI等

TCC 的使用模式

线程上下文的使用模式主要分为: 获取-> 设置 -> 使用 -> 还原 , 伪代码可以参考:

// 获取原类加载器

ClassLoader classLoader = Thread.currentThread().getContextClassLoader();

// 通过一些手段获取的目标类加载器

ClassLoader targetClassLoader = xxxx;

try {

// 将新的类加载器设置为当前上下文类加载器

Thread.currentThread().setContextClassLoader(targetClassLoader);

// 使用加载器加载一些自己需要的类

loadClass();

} finally {

// 还原

Thread.currentThread().setContextClassLoader(classLoader);

}

总结

当高层提供了统计的接口让低层去实现,同时又要在高层加载(或者实例化)这个类,那么就必须通过线程上下文类加载器帮助高层ClassLoader 加载这个类

父加载器不能访问使用子加载器加载的类,子加载器可以访问使用父加载器加载的类

就SPI服务而言,有些接口是启动类加载器加载,但具体的实现各个厂商有自己不同的实现方式,这些实现是不会被启动类加载器加载的,这样传统的双亲委托机制就无法满足 SPI 的要求。而通过设置当前线程的上下类加载器,就可以通过当前线程的上下文类加载器加载这些类。

Java中所有涉及SPI的加载动作都采用这种方式, 实现方案包括:  JDBC、JNDI、JCE以及JBI等

拓展学习点

Tomcat 中的类加载机制

SpringWeb 中类实现的机制

java 上下文加载器_【深入理解Java虚拟机 】线程的上下文类加载器相关推荐

  1. 没有为 ucrtbase.dll 加载符号_深入理解Java虚拟机(类加载机制)

    上一篇文章我们介绍了「类文件结构」,这一篇我们来看看虚拟机是如何加载类的. 我们的源代码经过编译器编译成字节码之后,最终都需要加载到虚拟机之后才能运行.虚拟机把描述类的数据从 Class 文件加载到内 ...

  2. java加载机制_详解Java类加载机制

    一:ClassLoader 从JVM结构图中可以看到,类加载器的作用是将Java类文件加载到Java虚拟机. HotSpot JVM结构,图片来自Java Garbage Collection Bas ...

  3. WebApi 数据保护操作未成功。这可能是由于未为当前线程的用户上下文加载用户配置文件导致的。当线程执行模拟时,可能会出现此情况。,ExceptionType:System.Security....

    在调用System.Security.Cryptography.ProtectedData.Protect方法来保护私密信息时,IIS可能会报以下错误:CryptographicException: ...

  4. 28 Java类的加载机制、什么是类的加载、类的生命周期、加载:查找并加载类的二进制数据、连接、初始化、类加载器、双亲委派模型、自定义类加载器

    28Java类的加载机制 28.1.什么是类的加载 28.2.类的生命周期 28.2.1.加载:查找并加载类的二进制数据 28.2.2.连接 28.2.3.初始化 28.3.类加载器 28.4.类的加 ...

  5. java 线程加载类_怎么判断java当前线程是否加载了一个类的字节码

    展开全部 原生的ClassLoader是有e68a843231313335323631343130323136353331333337616631一个方法判断类是否已经加载的/** * Returns ...

  6. java jvm垃圾回收算法_深入理解JVM虚拟机2:JVM垃圾回收基本原理和算法

    本文转自互联网,侵删 本系列文章将整理到我在GitHub上的<Java面试指南>仓库,更多精彩内容请到我的仓库里查看 喜欢的话麻烦点下Star哈 文章将同步到我的个人博客: www.how ...

  7. java中成员变量的加载时机_工作奇谈——JAVA高级特性之反射

    一.从问题入手 最近又要面试新人,所以翻了翻以前的代码,突然发现了一个有意思的问题. 问:如下一个Student类,请实例Student并对其成员变量赋值. public class Student ...

  8. java懒加载注解_在springboot中实现个别bean懒加载的操作

    懒加载---就是我们在spring容器启动的是先不把所有的bean都加载到spring的容器中去,而是在当需要用的时候,才把这个对象实例化到容器中. @Lazy 在需要懒加载的bean上加上@Lazy ...

  9. java 滚动加载数据_[Java教程]浏览器滚动条快到底部时自动加载数据

    [Java教程]浏览器滚动条快到底部时自动加载数据 0 2015-11-30 15:00:44 1 2 3 4 5 6 ");24 main.append(" hello worl ...

  10. java方法区内存泄露_深入理解java虚拟机-第二章:java内存区域与内存泄露异常...

    2.1概述: java将内存的管理(主要是回收工作),交由jvm管理,确实很省事,但是一点jvm因内存出现问题,排查起来将会很困难,为了能够成为独当一面的大牛呢,自然要了解vm是怎么去使用内存的. 2 ...

最新文章

  1. 最近做手机端,GPS,微信QQ分享总结的问题
  2. 亿级用户中心的设计与实践
  3. Django部署前准备
  4. tensorboard 远程
  5. PyTorch笔记: GPU上训练的模型加载到CPU/错误处理Attempting to deserialize object on a CUDA device but torch.cuda.is_a
  6. [crypto]-51.2-从rsa公钥中提取N和E
  7. linux下哪些软件能跑pin,Linux下4款常见远程工具比较
  8. 我的播客开通的第一天
  9. 乾颐堂军哥华为HCNP真题讲解(2017至2018版)真题更新版到来
  10. 以4%参数量比肩GPT-3!Deepmind 发布检索型 LM,或将成为 LM 发展新趋势!?
  11. ubuntu安装jre
  12. 表面缺陷检测:机器视觉检测技术
  13. Linux-基础部分
  14. Unity3D使用talkingData应用数据统计
  15. 我国高等教育财政投入效率分析与对策
  16. 互金平台乘着东风股价反弹,小赢科技为何成上涨“急先锋”?
  17. 搜索引擎点击日志聚类实现相关搜索
  18. MultiWarhead 球缺罩界面设计
  19. 美学心得(第二百三十七集) 罗国正
  20. 数分笔记整理21 - 数据处理项目 - 城市餐饮店铺选址分析 电商打折套路解析

热门文章

  1. c++一个类创建多个对象_C ++ | 创建一个类的多个对象
  2. kotlin键值对数组_Kotlin程序检查数组是否包含给定值
  3. Java File类boolean createNewFile()方法(带示例)
  4. linux sublime nodejs,Ubuntu环境下sublime3 nodejs安装与插件配置
  5. mysql 刷新二进制日志_使用binlog日志恢复MySQL数据库删除数据的方法
  6. mysql内置变量_MySQL常用内置变量
  7. 论文公式编号右对齐_论文不会写?最详细的论文排版技巧
  8. Redis 是如何执行的?
  9. 第 1-1 课:Java 程序是如何执行的?
  10. 我被面试官给虐懵了,竟然是因为我不懂Spring中的@Configuration