有许多地方能够看到线程上下文类加载的设置,比如在sun.misc.Launcher类的构造方法中,能够看到如下代码

先写一个例子建立感性认识

public class Test {
public static void main(String[] args) {
System.out.println(Thread.currentThread().getContextClassLoader());
System.out.println(Thread.class.getClassLoader());
}
}

输出

sun.misc.Launcher$AppClassLoader@18b4aac2
null

这是因为Thread类位于rt.jar包,而当前线程的上下文加载器,也就是加载了main函数所在类的加载器,其实就是系统类加载器

当前类加载器(Current ClassLoader)的概念

每个类都会使用自己的类加载器(即加载自身的类加载器)去加载所依赖的其他类。比如说ClassX引用了ClassY,那么ClassX的类加载器就会去加载ClassY,前提是ClassY尚未被加载。

线程上下文类加载器(Context ClassLoader)

线程上下文类加载器是从JDK1.2开始引入的,类Thread中的getContextClassLoader()于setContextClassLoader(ClassLoader cl)分别用来获取和设置上下文类加载器。

如果没有通过setContextClassLoader(ClassLoader cl)进行设置的话,线程将继承其父线程的上下文类加载器。

Java应用运行时的初始线程的上下文加载器是系统类加载器。线程中运行的代码,可以通过该类加载器来加载类与资源。

线程上下文类加载器的重要性

以JDBC为例,Connection是JDBC的标准接口,该接口位于rt.jar包里,而厂商提供的具体实现则是在厂商提供的jar包里。所以接口部分是由启动类加载器加载的,而实现是由系统类加载器加载的,这样就导致一个问题:根据双亲委托机制,父加载器加载的类无法看到子加载器加载的类,如果rt包中的某些类想要引用第三方厂商jar包里的实现类,就无法引用了。这是双亲委托模型在此类似情况下会出现的问题。这种由第三方厂商提供实现的方式,称为SPI(Service Provider Interface)

使用线程上下文类加载器,父ClassLoader可以使用当前线程Thread.currentThread().getContextClassLoader()所指定的classloader加载的类。这就改变了父ClassLoader不能使用子ClassLoader,或是其他没有直接父子关系的ClassLoader加载的类的情况,即改变了双亲委托模型。

更具体地来说,在main函数中使用ServiceLoader.load(Driver.class) 加载MySql驱动,由于ServiceLoader类在rt.jar包里,如果没有上下文类加载器这种机制,ServiceLoader类内部只会通过启动类加载器去尝试加载驱动,而驱动在第三方jar包里,因此它无法加载,导致失败。

线程上下文类加载器就是打破双亲委托模型的一种方式

【JVM学习笔记】线程上下文类加载器的更多相关文章

  1. 【JVM学习笔记】系统类加载器

    可以通过“java.system.class.loader"属性指定系统类加载器 默认情况下,该属性值为空: public class Test { public static void m ...

  2. 【JVM学习笔记】扩展类加载器

    扩展类加载器独有的特点,代码如下 public class Sample { } public class Test { static { System.out.println("Test ...

  3. JVM 线程上下文类加载器

    当前类加载器(Current ClassLoader) 每个类都会使用自己的类加载器(即加载自身的类加载器)来去加载其他类(指所依赖的类) 如果ClassX引用了ClassY,那么ClassX的类加载 ...

  4. 7. 通过JDBC源码来分析线程上下文类加载器以及SPI的使用

    目录 1. 什么是全盘负责委托机制 2. 为什么需要有线程上下文类加载器 2.1 使用JDBC的例子,分析为什么双亲委托机制不能实现要求 2.2 线程上下文类加载器的作用 3. 线程上下文类加载器的使 ...

  5. 通过JDBC驱动加载深刻理解线程上下文类加载器机制

    关于线程上下文类加载器已经在之前学得比较透了,作为一个收尾,这里用平常J2EE开发时JDBC连接Mysql数据库常见的一段代码通过分析它的底层进一步加深对线程上下文类加载器的理解,所以先来将连接应用代 ...

  6. 线程上下文类加载器ContextClassLoader内存泄漏隐患

    前提 今天(2020-01-18)在编写Netty相关代码的时候,从Netty源码中的ThreadDeathWatcher和GlobalEventExecutor追溯到两个和线程上下文类加载器Cont ...

  7. 深入理解Java类加载器(二):线程上下文类加载器

    摘要: 博文<深入理解Java类加载器(一):Java类加载原理解析>提到的类加载器的双亲委派模型并不是一个强制性的约束模型,而是Java设计者推荐给开发者的类加载器的实现方式.在Java ...

  8. 【Java虚拟机11】线程上下文类加载器

    前言 目前学习到的类加载的知识,都是基于[双亲委托机制]的.那么JDK难道就没有提供一种打破双亲委托机制的类加载机制吗? 答案是否定的. JDK为我们提供了一种打破双亲委托模型的机制:线程上下文类加载 ...

  9. 线程上下文类加载器(Context ClassLoader)

    1.线程上下文类加载器是从jdk1.2开始引入的,类Thread中的getContextClassLoader()与setContextClassLoader(ClassLoader c1),分别用来 ...

随机推荐

  1. python .pth 文件 和 site 模块

    python .pth 文件 和 site 模块 .pth 文件 该文件位于 python 的 /Lib/site-packages 目录下,可以有多个,在 .pth 文件中可以把其它目录添加到 sy ...

  2. RocketMQ原理分析 文章 精选【收集】

    一. 推荐文章 1.以下来自OSChina的 mingxungu https://itzones.cn/ RocketMQ运维监控 RocketMQ刷盘策略 RocketMQ消息重试 RocketMQ ...

  3. Linux权限操作(用户和组)

    useradd 添加用户useradd -u uid user 创建指定uid的用户-o 配合-u 不检查uid的唯一性-d 指定家目录-s 指定shell-r 创建系统用户-m 强制创建家目录-M ...

  4. 第二个爬虫之爬取知乎用户回答和文章并将所有内容保存到txt文件中

    自从这两天开始学爬虫,就一直想做个爬虫爬知乎.于是就开始动手了. 知乎用户动态采取的是动态加载的方式,也就是先加载一部分的动态,要一直滑道底才会加载另一部分的动态.要爬取全部的动态,就得先获取全部的u ...

  5. 【Android-自定义控件】 漂亮的Toast

    修改Toast属性,美化Toast //创建一个Toast Toast toast=new Toast(getApplicationContext()); //创建Toast中的文字 TextView ...

  6. linux系统编程--信号

    信号的概念 man 7 siganl  查看man手册 信号在我们的生活中随处可见, 如:古代战争中摔杯为号:现代战争中的信号弹:体育比赛中使用的信号枪......他们都有共性:1. 简单 2. 不能 ...

  7. RabbitMQ的下载与安装

    RabbitMQ的安装注意事项: 1. 系统的管理员账户不能是中文(win8) 2. 计算机名不能是中文(win8) 3. 推荐:使用默认的安装目录 4. 使用的计算机用户必须是管理员 如果安装不成功 ...

  8. Django-模板继承/组件/自定义标签

    一.标签tags for标签 遍历每一个元素:  写个for,然后 tab键自动生成for循环的结构,循环很基础,就这么简单的用,没有什么break之类的,复杂一些的功能,你要通过js def get ...

  9. AcWing:237. 程序自动分析(离散化 + 并查集)

    在实现程序自动分析的过程中,常常需要判定一些约束条件是否能被同时满足. 考虑一个约束满足问题的简化版本:假设x1,x2,x3,…x1,x2,x3,…代表程序中出现的变量,给定n个形如xi=xjxi=x ...

  10. legend3---11、php前端模块化开发

    legend3---11.php前端模块化开发 一.总结 一句话总结: 把常用的前端块(比如课程列表,比如评论列表)放进模块列表里面,通过外部php变量给数据,可以很好的实现复用和修改 页面调用 @p ...