有许多地方能够看到线程上下文类加载的设置,比如在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. Python3+Appium学习笔记04-自动下载apk

    在项目中,app更新后,都会发布新的apk版本,然后去蒲公英对应的网站上扫码下载对应的apk进行测试.所以就在想,通过app参数进行安装时,是否可以先通过代码去拉取一遍最新的apk安装包. ​ 因为学 ...

  2. jsp的标签库

    Java Server Pages Standard Tag Libray(JSTL):JSP 标准标签库,是一个定制标签类库的集合,用于解决一些常见的问题,例如迭代一个映射或者集合.条件测试.XML ...

  3. HAL库 TIM计数器及中断开启过程

    1.初始化TIM基本计数器参数 void MX_TIM2_Init(void) { TIM_ClockConfigTypeDef sClockSourceConfig = {}; TIM_Master ...

  4. BZOJ 1283: 序列 (最大费用流)

    题意 有n个正整数,要选取里面的一些数,在保证每m个连续的数中最多选k个的情况下,使得得到的值最大. 分析 我们可以把问题先转化为选k次,每一次每m个数只能选一个.那么根据贪心的策略,每m个里一定会选 ...

  5. 【方法】移动端H5如何调用相册和相机上传图片、音频、视频

    在移动端上传图片方法很简单,使用HTML5中的input:file供文件上传. <一>常用属性值: 1.accept:规定文件上传来提交的文件类型,此属性只能和type:file配合使用 ...

  6. java8 time计算时间差

    最近使用Java8编写代码时,需要计算时间差,现整理如下 前言 本次使用了Java8提供的ChronoUnit工具类,它主要提供以下几种时间维度 枚举 枚举 说明 NANOS 毫微秒(毫秒的10000 ...

  7. UVAlive 7414 Squeeze the Cylinders a,b,c三种步数 搜索+最短路

    题意:给你n个点(n<=50),然后有些点之间会有一条路,路是单向的,每个回合让你走a,b,c三种步数中的任意一种(a,b,c<=100),问你最少需要多少个回合才能保证一定能从1点到达n ...

  8. 初学mysql 如何删除数据库 如何安装mysql

    廖老师官网链接 这两个表格有个映射关系,就是根据Grade_ID可以在班级表中查找到对应的所有班级: 也就是Grade表的每一行对应Class表的多行,在关系数据库中,这种基于表(Table)的一对多 ...

  9. python3版 爬虫了解

    摘要:本文将使用Python3.4爬网页.爬图片.自动登录.并对HTTP协议做了一个简单的介绍.在进行爬虫之前,先简单来进行一个HTTP协议的讲解,这样下面再来进行爬虫就是理解更加清楚. 一.HTTP ...

  10. Java基础_通过模拟售票情景解决线程不安全问题

    用代码来模拟铁路售票系统,实现通过四个售票点发售某日某次列车的100张车票,一个售票点用一个线程表示 第一种方法:通过继承Thread类的方法创建线程 package com.Gary1; publi ...