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

线程上下文类加载器

线程上下文类加载器( 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 中类实现的机制

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/555273.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

You may use special comments to disable some warnings.Use // eslint-disable-next-line to ignore...

vue没写什么爆红 错误原因 ESLint] 对语法的要求过于严格导致编译的时候报上图那些错误。 要知道,这并不是代码有异常,而是代码格式有问题,这些错误并不会影响代码的执行结果。 解决方法 很简单,既然是ESLint 语法错误&#xff…

java is a like a_JAVA基础——is-a 、have-a、和 like-a的区别

1、is-a,has-a,like-a是什么在面向对象设计的领域里,有若干种设计思路,主要有如下三种:is-a、has-a、like-ajava中在类、接口、抽象类中有很多体现。了解java看这里:什么是Java了解类和对象看这里&#xff…

Java根据日期生成编号

1、Java根据日期生成编号 根据日期生成编号 1、使用 DateTimeFormatter DateTimeFormatter fmt DateTimeFormatter.ofPattern("yyyyMMddHHmmssSSS");//设置日期格式 String newsNo "xw"LocalDateTime.now().format(fmt);2、使用 SimpleDateFormat Si…

Java数字位数不足前面补0的几种办法

public static void main(String[] args) {int num6; DecimalFormat decimalFormat new DecimalFormat("000000");String numFormat decimalFormat .format(num);System.out.println(numFormat);//打印结果"000006" }Testpublic void test() {this.printT…

java jni 原理_JNI的实现原理

JNI接口函数和指针Java虚拟机访问本机代码通过调用JNI的功能特性。JNI的功能都可以通过一个接口指针。一个接口指针是一个指向指针的指针。这个指针指向一个一个指针数组,这个数组中的每一个成员指向一个函数入口。每个接口的功能是在一个预定义的内部数组的偏移量。…

jQuery ajax读取本地json文件_jQuery请求本地JSON文件,在谷歌浏览器运行时报跨域错误_Vscode使用Live Server

json文件 {"first":[{"name":"张三","sex":"男"},{"name":"李四","sex":"男"},{"name":"王武","sex":"男"},{"name":"李…

java执行curl命令_Java执行curl命令

Java执行curl命令需要注意的是,命令需要以数组的形式传递参数,就是把正常的命令以空格切分成数组就行了。而且参数前后不能有空格,不然会报错。具体的测试代码如下:import java.io.BufferedReader;import java.io.IOException;imp…

Vue打包并发布项目

一、 打包vue项目步骤: 1、对当前vue项目进行打包的命令如下: npm run build2、打包完成,会输出Build complete并且在vue项目中会生成一个名字为dist的打包文件。如下图: 二、 使用静态服务器工具包发布打包的vue项目 1、首先…

java线程安全例子_Java总结篇系列:Java多线程(三)

本文主要接着前面多线程的两篇文章总结Java多线程中的线程安全问题。一.一个典型的Java线程安全例子1 public classThreadTest {23 public static voidmain(String[] args) {4 Account account new Account("123456", 1000);5 DrawMoneyRunnable drawMoneyRunnable …

Grammarly:最优秀的日常英文写作辅助工具——论文英文校验

使用Grammarly也有一些心得,在此分享给大家。 1,Grammarly是什么? Grammarly是一款在线语法纠正和校对工具,支持Windows、Mac、iOS和Android等多个平台。它能够检查单词拼写、纠正标点符号、修正语法错误、调整语气以及给出风格…

Spring如何将@RestController的对象自动转换为json_@ResponseBody 注解原理

我正在看一段代码,其中我假设spring决定在幕后使用Jackson为RestController自动将对象转换为json RestController RequestMapping("/api") public class ApiController {private RoomServices roomServices;Autowiredpublic ApiController(RoomServices…

jetty java web_i-jetty 下的JavaWeb开发(一)

最近需要将android端作为服务器进行开发,让android作为服务器,现阶段技术并不是很成熟,主要的服务器有i-jetty,是基于PC端的jetty的移植。i-jetty同tomcat类似,也是Servlet的容器,但是i-jetty需要使用andro…

SpringMVC @RequestBody和@ResponseBody原理解析

SpringMVC RequestBody和ResponseBody原理解析 前言 RequestBody作用是将http请求解析为对应的对象。例如: http请求的参数(application/json格式): {"accountId": 10,"adGroupId": "12345678",…

java 高性能缓存_高性能Java缓存----Caffeine

简单介绍Caffeine是新出现的一个高性能的Java缓存,有了它完全可以代替Guava Cache,来实现更加高效的缓存;Caffeine采用了W-TinyLFU回收策略,集合了LRU和LFU的优点,提供了一个最佳的命中率,在效率上可以秒杀…

@ResponseBody 转化成json后与实体类字段名不一致_SpringMVC字符串解析成json对象(@RequestBody注解和@ResponseBody注解)

ResponseBody 转化成json后与实体类字段名不一致 实体类A字段名由B改成C后,Controller 中返回的List中字段名仍然是C 经过ResponseBody返回到前台后又变成了B 后来发现公司项目采用的是阿里的fastjson, 是开源的Json格式化工具库 此工具库是根据实体类…

java togglebutton_ToggleButton和Switch使用大全

本文转载自:Android零基础入门第21节:ToggleButton和Switch使用大全http://www.apkbus.com/blog-205190-68463.html(出处: 安卓巴士 - 安卓开发 - Android开发 - 安卓 - 移动互联网门户),转载应备注出处,尊重原创上期学习了CheckB…

Jackson,实现Bean和JSON之间的灵活转换(SpringMVC默认的JSON转换器)

Jackson介绍 Jackson是Java最受欢迎的JSON类库之一,包含两个不同的解析器: Jackson ObjectMapper,将JSON转化为Java对象,或者转换为Jackson特定的树结构Jackson JsonParser,JSON流解析器,每次只解析一个J…

MyBatis之工作原理,简单实体的增加、修改、删除、查询_Mybatis-原理总结

一、MyBatis之工作原理 MyBatis是一个半自动映射框架。所谓半自动,是相对Hibernate全表映射而言的,MyBatis需要手动匹配提供POJO、SQL和映射关系。 我们知道,JDBC有四个核心对象: (1)DriverManager&#…

MySQL优化:如何避免回表查询?_什么是索引覆盖?

数据库表结构: create table user (id int primary key,name varchar(20),sex varchar(5),index(name) )engineinnodb;select id,name where nameshenjianselect id,name,sex where nameshenjian多查询了一个属性,为何检索过程完全不同? 什…

mysql提示Column count doesn‘t match value count at row 1错误

我们在对数据库进行添加信息时可能会遇到如下错误: Column count doesn’t match value count at row 1 该错误的意思是传入表的字段数和values值的个数不一样 我总结了一下,主要有3个易错点: 1.要传入表中的字段数和values后面的值的个数不…